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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
bed806cb26
|
@ -2138,6 +2138,18 @@ MLXSW_ITEM32(reg, ptys, local_port, 0x00, 16, 8);
|
|||
*/
|
||||
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_1000BASE_KX BIT(1)
|
||||
#define MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 BIT(2)
|
||||
|
@ -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_40GBASE_SR4 BIT(15)
|
||||
#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_100GBASE_CR4 BIT(20)
|
||||
#define MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 BIT(21)
|
||||
|
@ -2184,6 +2197,13 @@ MLXSW_ITEM32(reg, ptys, eth_proto_admin, 0x18, 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,
|
||||
u32 proto_admin)
|
||||
{
|
||||
|
|
|
@ -1599,112 +1599,149 @@ static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset)
|
|||
}
|
||||
|
||||
struct mlxsw_sp_port_link_mode {
|
||||
enum ethtool_link_mode_bit_indices mask_ethtool;
|
||||
u32 mask;
|
||||
u32 supported;
|
||||
u32 advertised;
|
||||
u32 speed;
|
||||
};
|
||||
|
||||
static const struct mlxsw_sp_port_link_mode mlxsw_sp_port_link_mode[] = {
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T,
|
||||
.supported = SUPPORTED_100baseT_Full,
|
||||
.advertised = ADVERTISED_100baseT_Full,
|
||||
.speed = 100,
|
||||
},
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_TX,
|
||||
.speed = 100,
|
||||
.mask_ethtool = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
|
||||
.speed = SPEED_100,
|
||||
},
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_SGMII |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX,
|
||||
.supported = SUPPORTED_1000baseKX_Full,
|
||||
.advertised = ADVERTISED_1000baseKX_Full,
|
||||
.speed = 1000,
|
||||
.mask_ethtool = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
|
||||
.speed = SPEED_1000,
|
||||
},
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_T,
|
||||
.supported = SUPPORTED_10000baseT_Full,
|
||||
.advertised = ADVERTISED_10000baseT_Full,
|
||||
.speed = 10000,
|
||||
.mask_ethtool = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
|
||||
.speed = SPEED_10000,
|
||||
},
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4,
|
||||
.supported = SUPPORTED_10000baseKX4_Full,
|
||||
.advertised = ADVERTISED_10000baseKX4_Full,
|
||||
.speed = 10000,
|
||||
.mask_ethtool = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
|
||||
.speed = SPEED_10000,
|
||||
},
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR,
|
||||
.supported = SUPPORTED_10000baseKR_Full,
|
||||
.advertised = ADVERTISED_10000baseKR_Full,
|
||||
.speed = 10000,
|
||||
.mask_ethtool = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
|
||||
.speed = SPEED_10000,
|
||||
},
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_20GBASE_KR2,
|
||||
.supported = SUPPORTED_20000baseKR2_Full,
|
||||
.advertised = ADVERTISED_20000baseKR2_Full,
|
||||
.speed = 20000,
|
||||
.mask_ethtool = ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
|
||||
.speed = SPEED_20000,
|
||||
},
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4,
|
||||
.supported = SUPPORTED_40000baseCR4_Full,
|
||||
.advertised = ADVERTISED_40000baseCR4_Full,
|
||||
.speed = 40000,
|
||||
.mask_ethtool = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
|
||||
.speed = SPEED_40000,
|
||||
},
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4,
|
||||
.supported = SUPPORTED_40000baseKR4_Full,
|
||||
.advertised = ADVERTISED_40000baseKR4_Full,
|
||||
.speed = 40000,
|
||||
.mask_ethtool = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
|
||||
.speed = SPEED_40000,
|
||||
},
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4,
|
||||
.supported = SUPPORTED_40000baseSR4_Full,
|
||||
.advertised = ADVERTISED_40000baseSR4_Full,
|
||||
.speed = 40000,
|
||||
.mask_ethtool = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
|
||||
.speed = SPEED_40000,
|
||||
},
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4,
|
||||
.supported = SUPPORTED_40000baseLR4_Full,
|
||||
.advertised = ADVERTISED_40000baseLR4_Full,
|
||||
.speed = 40000,
|
||||
.mask_ethtool = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
|
||||
.speed = SPEED_40000,
|
||||
},
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR,
|
||||
.speed = 25000,
|
||||
.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_50GBASE_KR4 |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2 |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2,
|
||||
.speed = 50000,
|
||||
.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,
|
||||
.supported = SUPPORTED_56000baseKR4_Full,
|
||||
.advertised = ADVERTISED_56000baseKR4_Full,
|
||||
.speed = 56000,
|
||||
.mask_ethtool = ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT,
|
||||
.speed = SPEED_56000,
|
||||
},
|
||||
{
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
|
||||
.speed = 100000,
|
||||
.mask = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4,
|
||||
.mask_ethtool = ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT,
|
||||
.speed = SPEED_56000,
|
||||
},
|
||||
{
|
||||
.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)
|
||||
|
||||
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 |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
|
||||
|
@ -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_100GBASE_SR4 |
|
||||
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 |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
|
||||
MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX))
|
||||
return SUPPORTED_Backplane;
|
||||
return 0;
|
||||
ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
__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,
|
||||
struct ethtool_cmd *cmd)
|
||||
struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
u32 speed = SPEED_UNKNOWN;
|
||||
u8 duplex = DUPLEX_UNKNOWN;
|
||||
|
@ -1765,8 +1788,8 @@ static void mlxsw_sp_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto,
|
|||
}
|
||||
}
|
||||
out:
|
||||
ethtool_cmd_speed_set(cmd, speed);
|
||||
cmd->duplex = duplex;
|
||||
cmd->base.speed = speed;
|
||||
cmd->base.duplex = duplex;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_port_get_settings(struct net_device *dev,
|
||||
struct ethtool_cmd *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, ð_proto_cap,
|
||||
ð_proto_admin, ð_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)
|
||||
static u32
|
||||
mlxsw_sp_to_ptys_advert_link(const struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
u32 ptys_proto = 0;
|
||||
int 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;
|
||||
}
|
||||
return ptys_proto;
|
||||
|
@ -1863,61 +1852,113 @@ static u32 mlxsw_sp_to_ptys_upper_speed(u32 upper_speed)
|
|||
return ptys_proto;
|
||||
}
|
||||
|
||||
static int mlxsw_sp_port_set_settings(struct net_device *dev,
|
||||
struct ethtool_cmd *cmd)
|
||||
static void mlxsw_sp_port_get_link_supported(u32 eth_proto_cap,
|
||||
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 *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
|
||||
char ptys_pl[MLXSW_REG_PTYS_LEN];
|
||||
u8 autoneg_status;
|
||||
bool autoneg;
|
||||
int err;
|
||||
|
||||
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, ð_proto_cap, ð_proto_admin,
|
||||
ð_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);
|
||||
|
||||
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 speed;
|
||||
u32 eth_proto_new;
|
||||
u32 eth_proto_cap;
|
||||
u32 eth_proto_admin;
|
||||
u32 eth_proto_cap, eth_proto_new;
|
||||
bool autoneg;
|
||||
int err;
|
||||
|
||||
speed = ethtool_cmd_speed(cmd);
|
||||
|
||||
eth_proto_new = cmd->autoneg == AUTONEG_ENABLE ?
|
||||
mlxsw_sp_to_ptys_advert_link(cmd->advertising) :
|
||||
mlxsw_sp_to_ptys_speed(speed);
|
||||
|
||||
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");
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
mlxsw_reg_ptys_unpack(ptys_pl, ð_proto_cap, ð_proto_admin, NULL);
|
||||
mlxsw_reg_ptys_unpack(ptys_pl, ð_proto_cap, NULL, 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;
|
||||
if (!eth_proto_new) {
|
||||
netdev_err(dev, "Not supported proto admin requested");
|
||||
netdev_err(dev, "No supported speed requested\n");
|
||||
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);
|
||||
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
|
||||
if (err) {
|
||||
netdev_err(dev, "Failed to set proto admin");
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!netif_running(dev))
|
||||
return 0;
|
||||
|
||||
err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
|
||||
if (err) {
|
||||
netdev_err(dev, "Failed to set admin status");
|
||||
return err;
|
||||
}
|
||||
mlxsw_sp_port->link.autoneg = autoneg;
|
||||
|
||||
err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
|
||||
if (err) {
|
||||
netdev_err(dev, "Failed to set admin status");
|
||||
return err;
|
||||
}
|
||||
mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
|
||||
mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1931,8 +1972,8 @@ static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
|
|||
.set_phys_id = mlxsw_sp_port_set_phys_id,
|
||||
.get_ethtool_stats = mlxsw_sp_port_get_stats,
|
||||
.get_sset_count = mlxsw_sp_port_get_sset_count,
|
||||
.get_settings = mlxsw_sp_port_get_settings,
|
||||
.set_settings = mlxsw_sp_port_set_settings,
|
||||
.get_link_ksettings = mlxsw_sp_port_get_link_ksettings,
|
||||
.set_link_ksettings = mlxsw_sp_port_set_link_ksettings,
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -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.width = width;
|
||||
mlxsw_sp_port->mapping.lane = lane;
|
||||
mlxsw_sp_port->link.autoneg = 1;
|
||||
bytes = DIV_ROUND_UP(VLAN_N_VID, BITS_PER_BYTE);
|
||||
mlxsw_sp_port->active_vlans = kzalloc(bytes, GFP_KERNEL);
|
||||
if (!mlxsw_sp_port->active_vlans) {
|
||||
|
|
|
@ -341,7 +341,8 @@ struct mlxsw_sp_port {
|
|||
} vport;
|
||||
struct {
|
||||
u8 tx_pause:1,
|
||||
rx_pause:1;
|
||||
rx_pause:1,
|
||||
autoneg:1;
|
||||
} link;
|
||||
struct {
|
||||
struct ieee_ets *ets;
|
||||
|
|
Loading…
Reference in a new issue