Commit b9d66a36 authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller

mlxsw: spectrum: Add support for new ethtool API

Remove the deprecated {get,set}_settings callbacks and instead add
{get,set}_link_ksettings along with support for newly available speeds.
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 91bdc7a4
...@@ -2164,6 +2164,7 @@ MLXSW_ITEM32(reg, ptys, an_status, 0x04, 28, 4); ...@@ -2164,6 +2164,7 @@ MLXSW_ITEM32(reg, ptys, an_status, 0x04, 28, 4);
#define MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR BIT(14) #define MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR BIT(14)
#define MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 BIT(15) #define MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 BIT(15)
#define MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4 BIT(16) #define MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4 BIT(16)
#define MLXSW_REG_PTYS_ETH_SPEED_50GBASE_SR2 BIT(18)
#define MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR4 BIT(19) #define MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR4 BIT(19)
#define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 BIT(20) #define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 BIT(20)
#define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 BIT(21) #define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 BIT(21)
......
...@@ -1599,158 +1599,179 @@ static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset) ...@@ -1599,158 +1599,179 @@ static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset)
} }
struct mlxsw_sp_port_link_mode { struct mlxsw_sp_port_link_mode {
enum ethtool_link_mode_bit_indices mask_ethtool;
u32 mask; u32 mask;
u32 supported;
u32 advertised;
u32 speed; u32 speed;
}; };
static const struct mlxsw_sp_port_link_mode mlxsw_sp_port_link_mode[] = { static const struct mlxsw_sp_port_link_mode mlxsw_sp_port_link_mode[] = {
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T, .mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T,
.supported = SUPPORTED_100baseT_Full, .mask_ethtool = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
.advertised = ADVERTISED_100baseT_Full, .speed = SPEED_100,
.speed = 100,
},
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_TX,
.speed = 100,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_SGMII | .mask = MLXSW_REG_PTYS_ETH_SPEED_SGMII |
MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX, MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX,
.supported = SUPPORTED_1000baseKX_Full, .mask_ethtool = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
.advertised = ADVERTISED_1000baseKX_Full, .speed = SPEED_1000,
.speed = 1000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_T, .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_T,
.supported = SUPPORTED_10000baseT_Full, .mask_ethtool = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
.advertised = ADVERTISED_10000baseT_Full, .speed = SPEED_10000,
.speed = 10000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 | .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 |
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4, MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4,
.supported = SUPPORTED_10000baseKX4_Full, .mask_ethtool = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
.advertised = ADVERTISED_10000baseKX4_Full, .speed = SPEED_10000,
.speed = 10000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR | .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR | MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR, MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR,
.supported = SUPPORTED_10000baseKR_Full, .mask_ethtool = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
.advertised = ADVERTISED_10000baseKR_Full, .speed = SPEED_10000,
.speed = 10000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_20GBASE_KR2, .mask = MLXSW_REG_PTYS_ETH_SPEED_20GBASE_KR2,
.supported = SUPPORTED_20000baseKR2_Full, .mask_ethtool = ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
.advertised = ADVERTISED_20000baseKR2_Full, .speed = SPEED_20000,
.speed = 20000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4, .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4,
.supported = SUPPORTED_40000baseCR4_Full, .mask_ethtool = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
.advertised = ADVERTISED_40000baseCR4_Full, .speed = SPEED_40000,
.speed = 40000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4, .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4,
.supported = SUPPORTED_40000baseKR4_Full, .mask_ethtool = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
.advertised = ADVERTISED_40000baseKR4_Full, .speed = SPEED_40000,
.speed = 40000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4, .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4,
.supported = SUPPORTED_40000baseSR4_Full, .mask_ethtool = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
.advertised = ADVERTISED_40000baseSR4_Full, .speed = SPEED_40000,
.speed = 40000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4, .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4,
.supported = SUPPORTED_40000baseLR4_Full, .mask_ethtool = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
.advertised = ADVERTISED_40000baseLR4_Full, .speed = SPEED_40000,
.speed = 40000, },
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR,
.mask_ethtool = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
.speed = SPEED_25000,
},
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR,
.mask_ethtool = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
.speed = SPEED_25000,
},
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR,
.mask_ethtool = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
.speed = SPEED_25000,
},
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR,
.mask_ethtool = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
.speed = SPEED_25000,
},
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2,
.mask_ethtool = ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
.speed = SPEED_50000,
},
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2,
.mask_ethtool = ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
.speed = SPEED_50000,
},
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_SR2,
.mask_ethtool = ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
.speed = SPEED_50000,
},
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
.mask_ethtool = ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT,
.speed = SPEED_56000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR | .mask = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR | .mask_ethtool = ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT,
MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR, .speed = SPEED_56000,
.speed = 25000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR4 | .mask = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2 | .mask_ethtool = ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT,
MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2, .speed = SPEED_56000,
.speed = 50000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4, .mask = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
.supported = SUPPORTED_56000baseKR4_Full, .mask_ethtool = ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
.advertised = ADVERTISED_56000baseKR4_Full, .speed = SPEED_56000,
.speed = 56000, },
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4,
.mask_ethtool = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
.speed = SPEED_100000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 | .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4,
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 | .mask_ethtool = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 | .speed = SPEED_100000,
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4, },
.speed = 100000, {
.mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4,
.mask_ethtool = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
.speed = SPEED_100000,
},
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
.mask_ethtool = ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
.speed = SPEED_100000,
}, },
}; };
#define MLXSW_SP_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp_port_link_mode) #define MLXSW_SP_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp_port_link_mode)
static u32 mlxsw_sp_from_ptys_supported_port(u32 ptys_eth_proto) static void
mlxsw_sp_from_ptys_supported_port(u32 ptys_eth_proto,
struct ethtool_link_ksettings *cmd)
{ {
u32 modes = 0;
if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR | MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 | MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 |
MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 | MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 |
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 | MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
MLXSW_REG_PTYS_ETH_SPEED_SGMII)) MLXSW_REG_PTYS_ETH_SPEED_SGMII))
modes |= SUPPORTED_FIBRE; ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR | if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 | MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 |
MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 | MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 |
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 | MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX)) MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX))
modes |= SUPPORTED_Backplane; ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
return modes;
} }
static u32 mlxsw_sp_from_ptys_supported_link(u32 ptys_eth_proto) static void mlxsw_sp_from_ptys_link(u32 ptys_eth_proto, unsigned long *mode)
{ {
u32 modes = 0;
int i; int i;
for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) { for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) {
if (ptys_eth_proto & mlxsw_sp_port_link_mode[i].mask) if (ptys_eth_proto & mlxsw_sp_port_link_mode[i].mask)
modes |= mlxsw_sp_port_link_mode[i].supported; __set_bit(mlxsw_sp_port_link_mode[i].mask_ethtool,
mode);
} }
return modes;
}
static u32 mlxsw_sp_from_ptys_advert_link(u32 ptys_eth_proto)
{
u32 modes = 0;
int i;
for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) {
if (ptys_eth_proto & mlxsw_sp_port_link_mode[i].mask)
modes |= mlxsw_sp_port_link_mode[i].advertised;
}
return modes;
} }
static void mlxsw_sp_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto, static void mlxsw_sp_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto,
struct ethtool_cmd *cmd) struct ethtool_link_ksettings *cmd)
{ {
u32 speed = SPEED_UNKNOWN; u32 speed = SPEED_UNKNOWN;
u8 duplex = DUPLEX_UNKNOWN; u8 duplex = DUPLEX_UNKNOWN;
...@@ -1767,8 +1788,8 @@ static void mlxsw_sp_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto, ...@@ -1767,8 +1788,8 @@ static void mlxsw_sp_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto,
} }
} }
out: out:
ethtool_cmd_speed_set(cmd, speed); cmd->base.speed = speed;
cmd->duplex = duplex; cmd->base.duplex = duplex;
} }
static u8 mlxsw_sp_port_connector_port(u32 ptys_eth_proto) static u8 mlxsw_sp_port_connector_port(u32 ptys_eth_proto)
...@@ -1793,60 +1814,15 @@ static u8 mlxsw_sp_port_connector_port(u32 ptys_eth_proto) ...@@ -1793,60 +1814,15 @@ static u8 mlxsw_sp_port_connector_port(u32 ptys_eth_proto)
return PORT_OTHER; return PORT_OTHER;
} }
static int mlxsw_sp_port_get_settings(struct net_device *dev, static u32
struct ethtool_cmd *cmd) mlxsw_sp_to_ptys_advert_link(const struct ethtool_link_ksettings *cmd)
{
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
char ptys_pl[MLXSW_REG_PTYS_LEN];
u32 eth_proto_cap;
u32 eth_proto_admin;
u32 eth_proto_oper;
u8 autoneg_status;
u32 eth_proto_lp;
int err;
mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
if (err) {
netdev_err(dev, "Failed to get proto");
return err;
}
mlxsw_reg_ptys_unpack(ptys_pl, &eth_proto_cap,
&eth_proto_admin, &eth_proto_oper);
eth_proto_lp = mlxsw_reg_ptys_eth_proto_lp_advertise_get(ptys_pl);
autoneg_status = mlxsw_reg_ptys_an_status_get(ptys_pl);
cmd->supported = mlxsw_sp_from_ptys_supported_port(eth_proto_cap) |
mlxsw_sp_from_ptys_supported_link(eth_proto_cap) |
SUPPORTED_Pause | SUPPORTED_Asym_Pause |
SUPPORTED_Autoneg;
if (mlxsw_sp_port->link.autoneg) {
cmd->advertising =
mlxsw_sp_from_ptys_advert_link(eth_proto_admin);
cmd->advertising |= ADVERTISED_Autoneg;
cmd->autoneg = AUTONEG_ENABLE;
}
mlxsw_sp_from_ptys_speed_duplex(netif_carrier_ok(dev),
eth_proto_oper, cmd);
cmd->port = mlxsw_sp_port_connector_port(eth_proto_oper);
if (autoneg_status == MLXSW_REG_PTYS_AN_STATUS_OK && eth_proto_lp)
cmd->lp_advertising =
mlxsw_sp_from_ptys_advert_link(eth_proto_lp);
cmd->transceiver = XCVR_INTERNAL;
return 0;
}
static u32 mlxsw_sp_to_ptys_advert_link(u32 advertising)
{ {
u32 ptys_proto = 0; u32 ptys_proto = 0;
int i; int i;
for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) { for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) {
if (advertising & mlxsw_sp_port_link_mode[i].advertised) if (test_bit(mlxsw_sp_port_link_mode[i].mask_ethtool,
cmd->link_modes.advertising))
ptys_proto |= mlxsw_sp_port_link_mode[i].mask; ptys_proto |= mlxsw_sp_port_link_mode[i].mask;
} }
return ptys_proto; return ptys_proto;
...@@ -1876,65 +1852,113 @@ static u32 mlxsw_sp_to_ptys_upper_speed(u32 upper_speed) ...@@ -1876,65 +1852,113 @@ static u32 mlxsw_sp_to_ptys_upper_speed(u32 upper_speed)
return ptys_proto; return ptys_proto;
} }
static int mlxsw_sp_port_set_settings(struct net_device *dev, static void mlxsw_sp_port_get_link_supported(u32 eth_proto_cap,
struct ethtool_cmd *cmd) struct ethtool_link_ksettings *cmd)
{
ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause);
ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
mlxsw_sp_from_ptys_supported_port(eth_proto_cap, cmd);
mlxsw_sp_from_ptys_link(eth_proto_cap, cmd->link_modes.supported);
}
static void mlxsw_sp_port_get_link_advertise(u32 eth_proto_admin, bool autoneg,
struct ethtool_link_ksettings *cmd)
{ {
if (!autoneg)
return;
ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
mlxsw_sp_from_ptys_link(eth_proto_admin, cmd->link_modes.advertising);
}
static void
mlxsw_sp_port_get_link_lp_advertise(u32 eth_proto_lp, u8 autoneg_status,
struct ethtool_link_ksettings *cmd)
{
if (autoneg_status != MLXSW_REG_PTYS_AN_STATUS_OK || !eth_proto_lp)
return;
ethtool_link_ksettings_add_link_mode(cmd, lp_advertising, Autoneg);
mlxsw_sp_from_ptys_link(eth_proto_lp, cmd->link_modes.lp_advertising);
}
static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *cmd)
{
u32 eth_proto_cap, eth_proto_admin, eth_proto_oper, eth_proto_lp;
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
char ptys_pl[MLXSW_REG_PTYS_LEN]; char ptys_pl[MLXSW_REG_PTYS_LEN];
u32 speed; u8 autoneg_status;
u32 eth_proto_new;
u32 eth_proto_cap;
u32 eth_proto_admin;
bool autoneg; bool autoneg;
int err; int err;
autoneg = cmd->autoneg == AUTONEG_ENABLE; autoneg = mlxsw_sp_port->link.autoneg;
speed = ethtool_cmd_speed(cmd); mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
if (err)
return err;
mlxsw_reg_ptys_unpack(ptys_pl, &eth_proto_cap, &eth_proto_admin,
&eth_proto_oper);
mlxsw_sp_port_get_link_supported(eth_proto_cap, cmd);
eth_proto_new = autoneg ? mlxsw_sp_port_get_link_advertise(eth_proto_admin, autoneg, cmd);
mlxsw_sp_to_ptys_advert_link(cmd->advertising) :
mlxsw_sp_to_ptys_speed(speed); eth_proto_lp = mlxsw_reg_ptys_eth_proto_lp_advertise_get(ptys_pl);
autoneg_status = mlxsw_reg_ptys_an_status_get(ptys_pl);
mlxsw_sp_port_get_link_lp_advertise(eth_proto_lp, autoneg_status, cmd);
cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
cmd->base.port = mlxsw_sp_port_connector_port(eth_proto_oper);
mlxsw_sp_from_ptys_speed_duplex(netif_carrier_ok(dev), eth_proto_oper,
cmd);
return 0;
}
static int
mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
const struct ethtool_link_ksettings *cmd)
{
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
char ptys_pl[MLXSW_REG_PTYS_LEN];
u32 eth_proto_cap, eth_proto_new;
bool autoneg;
int err;
mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0); mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
if (err) { if (err)
netdev_err(dev, "Failed to get proto");
return err; return err;
} mlxsw_reg_ptys_unpack(ptys_pl, &eth_proto_cap, NULL, NULL);
mlxsw_reg_ptys_unpack(ptys_pl, &eth_proto_cap, &eth_proto_admin, NULL);
autoneg = cmd->base.autoneg == AUTONEG_ENABLE;
eth_proto_new = autoneg ?
mlxsw_sp_to_ptys_advert_link(cmd) :
mlxsw_sp_to_ptys_speed(cmd->base.speed);
eth_proto_new = eth_proto_new & eth_proto_cap; eth_proto_new = eth_proto_new & eth_proto_cap;
if (!eth_proto_new) { if (!eth_proto_new) {
netdev_err(dev, "Not supported proto admin requested"); netdev_err(dev, "No supported speed requested\n");
return -EINVAL; return -EINVAL;
} }
if (eth_proto_new == eth_proto_admin)
return 0;
mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, eth_proto_new); mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, eth_proto_new);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
if (err) { if (err)
netdev_err(dev, "Failed to set proto admin");
return err; return err;
}
if (!netif_running(dev)) if (!netif_running(dev))
return 0; return 0;
mlxsw_sp_port->link.autoneg = autoneg; mlxsw_sp_port->link.autoneg = autoneg;
err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false); mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
if (err) { mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
netdev_err(dev, "Failed to set admin status");
return err;
}
err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
if (err) {
netdev_err(dev, "Failed to set admin status");
return err;
}
return 0; return 0;
} }
...@@ -1948,8 +1972,8 @@ static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = { ...@@ -1948,8 +1972,8 @@ static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
.set_phys_id = mlxsw_sp_port_set_phys_id, .set_phys_id = mlxsw_sp_port_set_phys_id,
.get_ethtool_stats = mlxsw_sp_port_get_stats, .get_ethtool_stats = mlxsw_sp_port_get_stats,
.get_sset_count = mlxsw_sp_port_get_sset_count, .get_sset_count = mlxsw_sp_port_get_sset_count,
.get_settings = mlxsw_sp_port_get_settings, .get_link_ksettings = mlxsw_sp_port_get_link_ksettings,
.set_settings = mlxsw_sp_port_set_settings, .set_link_ksettings = mlxsw_sp_port_set_link_ksettings,
}; };
static int static int
......
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