Commit 8e1ed739 authored by Tal Bar's avatar Tal Bar Committed by David S. Miller

mlxsw: spectrum: Add support for auto-negotiation disable mode

In 'auto-neg off' the device have sent AN (auto-negotiation) frames
with the forced speed. Thus, fix it using an_disable_admin field in
Port type and speed (PTYS) register. This field indicates if speed
negotiation frames would be send by the port or not.

Add the field and enable/disable it for 'auto-neg on/off', make the
port to start/stop sending AN (auto-negotiation) frames. Note that for
SwitchX2 the behavior doesn't change (i.e support only AN enabled with
forced speed).
Signed-off-by: default avatarTal Bar <talb@mellanox.com>
Reviewed-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1c6e1037
...@@ -2872,6 +2872,14 @@ static inline void mlxsw_reg_pmtu_pack(char *payload, u8 local_port, ...@@ -2872,6 +2872,14 @@ static inline void mlxsw_reg_pmtu_pack(char *payload, u8 local_port,
MLXSW_REG_DEFINE(ptys, MLXSW_REG_PTYS_ID, MLXSW_REG_PTYS_LEN); MLXSW_REG_DEFINE(ptys, MLXSW_REG_PTYS_ID, MLXSW_REG_PTYS_LEN);
/* an_disable_admin
* Auto negotiation disable administrative configuration
* 0 - Device doesn't support AN disable.
* 1 - Device supports AN disable.
* Access: RW
*/
MLXSW_ITEM32(reg, ptys, an_disable_admin, 0x00, 30, 1);
/* reg_ptys_local_port /* reg_ptys_local_port
* Local port number. * Local port number.
* Access: Index * Access: Index
...@@ -3000,12 +3008,13 @@ MLXSW_ITEM32(reg, ptys, ib_proto_oper, 0x28, 0, 16); ...@@ -3000,12 +3008,13 @@ MLXSW_ITEM32(reg, ptys, ib_proto_oper, 0x28, 0, 16);
MLXSW_ITEM32(reg, ptys, eth_proto_lp_advertise, 0x30, 0, 32); MLXSW_ITEM32(reg, ptys, eth_proto_lp_advertise, 0x30, 0, 32);
static inline void mlxsw_reg_ptys_eth_pack(char *payload, u8 local_port, static inline void mlxsw_reg_ptys_eth_pack(char *payload, u8 local_port,
u32 proto_admin) u32 proto_admin, bool autoneg)
{ {
MLXSW_REG_ZERO(ptys, payload); MLXSW_REG_ZERO(ptys, payload);
mlxsw_reg_ptys_local_port_set(payload, local_port); mlxsw_reg_ptys_local_port_set(payload, local_port);
mlxsw_reg_ptys_proto_mask_set(payload, MLXSW_REG_PTYS_PROTO_MASK_ETH); mlxsw_reg_ptys_proto_mask_set(payload, MLXSW_REG_PTYS_PROTO_MASK_ETH);
mlxsw_reg_ptys_eth_proto_admin_set(payload, proto_admin); mlxsw_reg_ptys_eth_proto_admin_set(payload, proto_admin);
mlxsw_reg_ptys_an_disable_admin_set(payload, !autoneg);
} }
static inline void mlxsw_reg_ptys_eth_unpack(char *payload, static inline void mlxsw_reg_ptys_eth_unpack(char *payload,
......
...@@ -2390,7 +2390,7 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev, ...@@ -2390,7 +2390,7 @@ static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev,
int err; int err;
autoneg = mlxsw_sp_port->link.autoneg; autoneg = mlxsw_sp_port->link.autoneg;
mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0); mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0, false);
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)
return err; return err;
...@@ -2424,7 +2424,7 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev, ...@@ -2424,7 +2424,7 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
bool autoneg; bool autoneg;
int err; int err;
mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0); mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0, false);
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)
return err; return err;
...@@ -2442,7 +2442,7 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev, ...@@ -2442,7 +2442,7 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
} }
mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port,
eth_proto_new); eth_proto_new, autoneg);
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)
return err; return err;
...@@ -2653,7 +2653,7 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 width) ...@@ -2653,7 +2653,7 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 width)
eth_proto_admin = mlxsw_sp_to_ptys_upper_speed(upper_speed); eth_proto_admin = mlxsw_sp_to_ptys_upper_speed(upper_speed);
mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port,
eth_proto_admin); eth_proto_admin, mlxsw_sp_port->link.autoneg);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
} }
......
...@@ -789,7 +789,7 @@ mlxsw_sx_port_get_link_ksettings(struct net_device *dev, ...@@ -789,7 +789,7 @@ mlxsw_sx_port_get_link_ksettings(struct net_device *dev,
u32 supported, advertising, lp_advertising; u32 supported, advertising, lp_advertising;
int err; int err;
mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 0); mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 0, false);
err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
if (err) { if (err) {
netdev_err(dev, "Failed to get proto"); netdev_err(dev, "Failed to get proto");
...@@ -879,7 +879,7 @@ mlxsw_sx_port_set_link_ksettings(struct net_device *dev, ...@@ -879,7 +879,7 @@ mlxsw_sx_port_set_link_ksettings(struct net_device *dev,
mlxsw_sx_to_ptys_advert_link(advertising) : mlxsw_sx_to_ptys_advert_link(advertising) :
mlxsw_sx_to_ptys_speed(speed); mlxsw_sx_to_ptys_speed(speed);
mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 0); mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, 0, false);
err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); err = mlxsw_reg_query(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
if (err) { if (err) {
netdev_err(dev, "Failed to get proto"); netdev_err(dev, "Failed to get proto");
...@@ -897,7 +897,7 @@ mlxsw_sx_port_set_link_ksettings(struct net_device *dev, ...@@ -897,7 +897,7 @@ mlxsw_sx_port_set_link_ksettings(struct net_device *dev,
return 0; return 0;
mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port,
eth_proto_new); eth_proto_new, true);
err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
if (err) { if (err) {
netdev_err(dev, "Failed to set proto admin"); netdev_err(dev, "Failed to set proto admin");
...@@ -1029,7 +1029,7 @@ mlxsw_sx_port_speed_by_width_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 width) ...@@ -1029,7 +1029,7 @@ mlxsw_sx_port_speed_by_width_set(struct mlxsw_sx_port *mlxsw_sx_port, u8 width)
eth_proto_admin = mlxsw_sx_to_ptys_upper_speed(upper_speed); eth_proto_admin = mlxsw_sx_to_ptys_upper_speed(upper_speed);
mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port, mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sx_port->local_port,
eth_proto_admin); eth_proto_admin, true);
return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl); return mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(ptys), ptys_pl);
} }
......
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