Commit bed806cb authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-ethtool'

Jiri Pirko says:

====================
mlxsw: ethtool enhancements

Ido says:

Patches 1-4 do some minor cleanup in current ethtool ops. Patch 5
replace legacy {get,set}_settings callbacks with
{get,set}_link_ksettings.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 36a19b29 b9d66a36
...@@ -2138,6 +2138,18 @@ MLXSW_ITEM32(reg, ptys, local_port, 0x00, 16, 8); ...@@ -2138,6 +2138,18 @@ MLXSW_ITEM32(reg, ptys, local_port, 0x00, 16, 8);
*/ */
MLXSW_ITEM32(reg, ptys, proto_mask, 0x00, 0, 3); MLXSW_ITEM32(reg, ptys, proto_mask, 0x00, 0, 3);
enum {
MLXSW_REG_PTYS_AN_STATUS_NA,
MLXSW_REG_PTYS_AN_STATUS_OK,
MLXSW_REG_PTYS_AN_STATUS_FAIL,
};
/* reg_ptys_an_status
* Autonegotiation status.
* Access: RO
*/
MLXSW_ITEM32(reg, ptys, an_status, 0x04, 28, 4);
#define MLXSW_REG_PTYS_ETH_SPEED_SGMII BIT(0) #define MLXSW_REG_PTYS_ETH_SPEED_SGMII BIT(0)
#define MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX BIT(1) #define MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX BIT(1)
#define MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 BIT(2) #define MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 BIT(2)
...@@ -2152,6 +2164,7 @@ MLXSW_ITEM32(reg, ptys, proto_mask, 0x00, 0, 3); ...@@ -2152,6 +2164,7 @@ MLXSW_ITEM32(reg, ptys, proto_mask, 0x00, 0, 3);
#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)
...@@ -2184,6 +2197,13 @@ MLXSW_ITEM32(reg, ptys, eth_proto_admin, 0x18, 0, 32); ...@@ -2184,6 +2197,13 @@ MLXSW_ITEM32(reg, ptys, eth_proto_admin, 0x18, 0, 32);
*/ */
MLXSW_ITEM32(reg, ptys, eth_proto_oper, 0x24, 0, 32); MLXSW_ITEM32(reg, ptys, eth_proto_oper, 0x24, 0, 32);
/* reg_ptys_eth_proto_lp_advertise
* The protocols that were advertised by the link partner during
* autonegotiation.
* Access: RO
*/
MLXSW_ITEM32(reg, ptys, eth_proto_lp_advertise, 0x30, 0, 32);
static inline void mlxsw_reg_ptys_pack(char *payload, u8 local_port, static inline void mlxsw_reg_ptys_pack(char *payload, u8 local_port,
u32 proto_admin) u32 proto_admin)
{ {
......
...@@ -1599,112 +1599,149 @@ static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset) ...@@ -1599,112 +1599,149 @@ 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_25GBASE_CR | .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2,
MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR | .mask_ethtool = ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR, .speed = SPEED_50000,
.speed = 25000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR4 | .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2,
MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2 | .mask_ethtool = ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2, .speed = SPEED_50000,
.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 = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
.supported = SUPPORTED_56000baseKR4_Full, .mask_ethtool = ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT,
.advertised = ADVERTISED_56000baseKR4_Full, .speed = SPEED_56000,
.speed = 56000,
}, },
{ {
.mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 | .mask = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 | .mask_ethtool = ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT,
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 | .speed = SPEED_56000,
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4, },
.speed = 100000, {
.mask = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
.mask_ethtool = ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT,
.speed = SPEED_56000,
},
{
.mask = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
.mask_ethtool = ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
.speed = 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_SR4,
.mask_ethtool = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
.speed = 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)
{ {
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 |
...@@ -1712,43 +1749,29 @@ static u32 mlxsw_sp_from_ptys_supported_port(u32 ptys_eth_proto) ...@@ -1712,43 +1749,29 @@ static u32 mlxsw_sp_from_ptys_supported_port(u32 ptys_eth_proto)
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))
return 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))
return SUPPORTED_Backplane; ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
return 0;
}
static u32 mlxsw_sp_from_ptys_supported_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].supported;
}
return modes;
} }
static u32 mlxsw_sp_from_ptys_advert_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].advertised; __set_bit(mlxsw_sp_port_link_mode[i].mask_ethtool,
mode);
} }
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;
...@@ -1765,8 +1788,8 @@ static void mlxsw_sp_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto, ...@@ -1765,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)
...@@ -1791,49 +1814,15 @@ static u8 mlxsw_sp_port_connector_port(u32 ptys_eth_proto) ...@@ -1791,49 +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;
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);
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;
cmd->advertising = mlxsw_sp_from_ptys_advert_link(eth_proto_admin);
mlxsw_sp_from_ptys_speed_duplex(netif_carrier_ok(dev),
eth_proto_oper, cmd);
eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
cmd->port = mlxsw_sp_port_connector_port(eth_proto_oper);
cmd->lp_advertising = mlxsw_sp_from_ptys_advert_link(eth_proto_oper);
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;
...@@ -1863,61 +1852,113 @@ static u32 mlxsw_sp_to_ptys_upper_speed(u32 upper_speed) ...@@ -1863,61 +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; bool autoneg;
u32 eth_proto_cap;
u32 eth_proto_admin;
int err; int err;
speed = ethtool_cmd_speed(cmd); autoneg = mlxsw_sp_port->link.autoneg;
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);
mlxsw_sp_port_get_link_advertise(eth_proto_admin, autoneg, cmd);
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);
eth_proto_new = cmd->autoneg == AUTONEG_ENABLE ? cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
mlxsw_sp_to_ptys_advert_link(cmd->advertising) : cmd->base.port = mlxsw_sp_port_connector_port(eth_proto_oper);
mlxsw_sp_to_ptys_speed(speed); 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;
err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false); mlxsw_sp_port->link.autoneg = autoneg;
if (err) {
netdev_err(dev, "Failed to set admin status");
return err;
}
err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true); 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;
}
return 0; return 0;
} }
...@@ -1931,8 +1972,8 @@ static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = { ...@@ -1931,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
...@@ -2082,6 +2123,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, ...@@ -2082,6 +2123,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
mlxsw_sp_port->mapping.module = module; mlxsw_sp_port->mapping.module = module;
mlxsw_sp_port->mapping.width = width; mlxsw_sp_port->mapping.width = width;
mlxsw_sp_port->mapping.lane = lane; mlxsw_sp_port->mapping.lane = lane;
mlxsw_sp_port->link.autoneg = 1;
bytes = DIV_ROUND_UP(VLAN_N_VID, BITS_PER_BYTE); bytes = DIV_ROUND_UP(VLAN_N_VID, BITS_PER_BYTE);
mlxsw_sp_port->active_vlans = kzalloc(bytes, GFP_KERNEL); mlxsw_sp_port->active_vlans = kzalloc(bytes, GFP_KERNEL);
if (!mlxsw_sp_port->active_vlans) { if (!mlxsw_sp_port->active_vlans) {
......
...@@ -341,7 +341,8 @@ struct mlxsw_sp_port { ...@@ -341,7 +341,8 @@ struct mlxsw_sp_port {
} vport; } vport;
struct { struct {
u8 tx_pause:1, u8 tx_pause:1,
rx_pause:1; rx_pause:1,
autoneg:1;
} link; } link;
struct { struct {
struct ieee_ets *ets; struct ieee_ets *ets;
......
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