mlxsw: spectrum: Correctly report autonegotiation
authorIdo Schimmel <idosch@mellanox.com>
Mon, 12 Sep 2016 11:26:23 +0000 (13:26 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 13 Sep 2016 16:16:33 +0000 (12:16 -0400)
Up until now the device always reported autonegotiation to be off
although it was on by default.

Allow the user to disable / enable autonegotiation and report its status
correctly.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h

index a7efd2a..cbec5f3 100644 (file)
@@ -1815,7 +1815,12 @@ static int mlxsw_sp_port_get_settings(struct net_device *dev,
                         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);
+       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);
 
@@ -1873,11 +1878,13 @@ static int mlxsw_sp_port_set_settings(struct net_device *dev,
        u32 eth_proto_new;
        u32 eth_proto_cap;
        u32 eth_proto_admin;
+       bool autoneg;
        int err;
 
+       autoneg = cmd->autoneg == AUTONEG_ENABLE;
        speed = ethtool_cmd_speed(cmd);
 
-       eth_proto_new = cmd->autoneg == AUTONEG_ENABLE ?
+       eth_proto_new = autoneg ?
                mlxsw_sp_to_ptys_advert_link(cmd->advertising) :
                mlxsw_sp_to_ptys_speed(speed);
 
@@ -1907,6 +1914,8 @@ static int mlxsw_sp_port_set_settings(struct net_device *dev,
        if (!netif_running(dev))
                return 0;
 
+       mlxsw_sp_port->link.autoneg = autoneg;
+
        err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
        if (err) {
                netdev_err(dev, "Failed to set admin status");
@@ -2082,6 +2091,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) {
index 31a2f3d..969c250 100644 (file)
@@ -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;