Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / intel / ixgbe / ixgbe_82599.c
index 203a00c2433027c19f824bd9ddb84ed6fa0cb5bd..7946da94b2286a1baba9daf19c84ffe70f07e756 100644 (file)
@@ -59,12 +59,34 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
                                          bool autoneg_wait_to_complete);
 static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
 
+static bool ixgbe_mng_enabled(struct ixgbe_hw *hw)
+{
+       u32 fwsm, manc, factps;
+
+       fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+       if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT)
+               return false;
+
+       manc = IXGBE_READ_REG(hw, IXGBE_MANC);
+       if (!(manc & IXGBE_MANC_RCV_TCO_EN))
+               return false;
+
+       factps = IXGBE_READ_REG(hw, IXGBE_FACTPS);
+       if (factps & IXGBE_FACTPS_MNGCG)
+               return false;
+
+       return true;
+}
+
 static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
 {
        struct ixgbe_mac_info *mac = &hw->mac;
 
-       /* enable the laser control functions for SFP+ fiber */
-       if (mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) {
+       /* enable the laser control functions for SFP+ fiber
+        * and MNG not enabled
+        */
+       if ((mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
+           !hw->mng_fw_enabled) {
                mac->ops.disable_tx_laser =
                                       &ixgbe_disable_tx_laser_multispeed_fiber;
                mac->ops.enable_tx_laser =
@@ -563,7 +585,8 @@ static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
                        return status;
 
                /* Flap the tx laser if it has not already been done */
-               hw->mac.ops.flap_tx_laser(hw);
+               if (hw->mac.ops.flap_tx_laser)
+                       hw->mac.ops.flap_tx_laser(hw);
 
                /*
                 * Wait for the controller to acquire link.  Per IEEE 802.3ap,
@@ -615,7 +638,8 @@ static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
                        return status;
 
                /* Flap the tx laser if it has not already been done */
-               hw->mac.ops.flap_tx_laser(hw);
+               if (hw->mac.ops.flap_tx_laser)
+                       hw->mac.ops.flap_tx_laser(hw);
 
                /* Wait for the link partner to also set speed */
                msleep(100);
@@ -933,6 +957,7 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
        ixgbe_link_speed link_speed;
        s32 status;
        u32 ctrl, i, autoc, autoc2;
+       u32 curr_lms;
        bool link_up = false;
 
        /* Call adapter stop to disable tx/rx and clear interrupts */
@@ -964,6 +989,9 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
        if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL)
                hw->phy.ops.reset(hw);
 
+       /* remember AUTOC LMS from before we reset */
+       curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) & IXGBE_AUTOC_LMS_MASK;
+
 mac_reset_top:
        /*
         * Issue global reset to the MAC. Needs to be SW reset if link is up.
@@ -1019,6 +1047,19 @@ mac_reset_top:
                hw->mac.orig_autoc2 = autoc2;
                hw->mac.orig_link_settings_stored = true;
        } else {
+
+               /* If MNG FW is running on a multi-speed device that
+                * doesn't autoneg with out driver support we need to
+                * leave LMS in the state it was before we MAC reset.
+                * Likewise if we support WoL we don't want change the
+                * LMS state either.
+                */
+               if ((hw->phy.multispeed_fiber && hw->mng_fw_enabled) ||
+                   hw->wol_supported)
+                       hw->mac.orig_autoc =
+                               (hw->mac.orig_autoc & ~IXGBE_AUTOC_LMS_MASK) |
+                               curr_lms;
+
                if (autoc != hw->mac.orig_autoc) {
                        /* Need SW/FW semaphore around AUTOC writes if LESM is
                         * on, likewise reset_pipeline requires us to hold
@@ -2216,7 +2257,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
        .release_swfw_sync      = &ixgbe_release_swfw_sync,
        .get_thermal_sensor_data = &ixgbe_get_thermal_sensor_data_generic,
        .init_thermal_sensor_thresh = &ixgbe_init_thermal_sensor_thresh_generic,
-
+       .mng_fw_enabled         = &ixgbe_mng_enabled,
 };
 
 static struct ixgbe_eeprom_operations eeprom_ops_82599 = {