net: thunderx: Switchon carrier only upon interface link up
authorSunil Goutham <sgoutham@cavium.com>
Wed, 2 Dec 2015 10:06:16 +0000 (15:36 +0530)
committerDavid S. Miller <davem@davemloft.net>
Wed, 2 Dec 2015 20:58:50 +0000 (15:58 -0500)
Call netif_carrier_on() only if interface's link is up. Switching this on
upon IFF_UP by default, is causing issues with ethernet channel bonding
in LACP mode. Initial NETDEV_CHANGE notification was being skipped.

Also fixed some issues with link/speed/duplex reporting via ethtool.

Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
drivers/net/ethernet/cavium/thunder/nicvf_main.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.c

index af54c10945c25175e344ebf052e47e88c62219a3..a12b2e38cf61221fc4de44f6395eb60de76825a5 100644 (file)
@@ -112,6 +112,13 @@ static int nicvf_get_settings(struct net_device *netdev,
 
        cmd->supported = 0;
        cmd->transceiver = XCVR_EXTERNAL;
+
+       if (!nic->link_up) {
+               cmd->duplex = DUPLEX_UNKNOWN;
+               ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
+               return 0;
+       }
+
        if (nic->speed <= 1000) {
                cmd->port = PORT_MII;
                cmd->autoneg = AUTONEG_ENABLE;
@@ -125,6 +132,13 @@ static int nicvf_get_settings(struct net_device *netdev,
        return 0;
 }
 
+static u32 nicvf_get_link(struct net_device *netdev)
+{
+       struct nicvf *nic = netdev_priv(netdev);
+
+       return nic->link_up;
+}
+
 static void nicvf_get_drvinfo(struct net_device *netdev,
                              struct ethtool_drvinfo *info)
 {
@@ -660,7 +674,7 @@ static int nicvf_set_channels(struct net_device *dev,
 
 static const struct ethtool_ops nicvf_ethtool_ops = {
        .get_settings           = nicvf_get_settings,
-       .get_link               = ethtool_op_get_link,
+       .get_link               = nicvf_get_link,
        .get_drvinfo            = nicvf_get_drvinfo,
        .get_msglevel           = nicvf_get_msglevel,
        .set_msglevel           = nicvf_set_msglevel,
index 7f709cbdcd87d2f0a0beedd338437218ee0af094..dde8dc720cd3f3b7d513776662a4f05b1241486d 100644 (file)
@@ -1057,6 +1057,7 @@ int nicvf_stop(struct net_device *netdev)
 
        netif_carrier_off(netdev);
        netif_tx_stop_all_queues(nic->netdev);
+       nic->link_up = false;
 
        /* Teardown secondary qsets first */
        if (!nic->sqs_mode) {
@@ -1211,9 +1212,6 @@ int nicvf_open(struct net_device *netdev)
        nic->drv_stats.txq_stop = 0;
        nic->drv_stats.txq_wake = 0;
 
-       netif_carrier_on(netdev);
-       netif_tx_start_all_queues(netdev);
-
        return 0;
 cleanup:
        nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0);
index 6534b73620911728edb120fbd8129864250f2684..d77e41a459b92eac6d42f90d050a307cd85d1c2b 100644 (file)
@@ -612,6 +612,8 @@ static void bgx_poll_for_link(struct work_struct *work)
                lmac->last_duplex = 1;
        } else {
                lmac->link_up = 0;
+               lmac->last_speed = SPEED_UNKNOWN;
+               lmac->last_duplex = DUPLEX_UNKNOWN;
        }
 
        if (lmac->last_link != lmac->link_up) {