]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/ixgbe/ixgbe_main.c
ixgbe: cleanup race conditions in link setup
[net-next-2.6.git] / drivers / net / ixgbe / ixgbe_main.c
index b798501500e6f039540c6c8ef2cd43b52bd4335a..0128fe666f0be9384586cab4e2176bb3c81088d2 100644 (file)
@@ -1712,17 +1712,18 @@ static void ixgbe_check_sfp_event(struct ixgbe_adapter *adapter, u32 eicr)
 {
        struct ixgbe_hw *hw = &adapter->hw;
 
+       if (eicr & IXGBE_EICR_GPI_SDP2) {
+               /* Clear the interrupt */
+               IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
+               if (!test_bit(__IXGBE_DOWN, &adapter->state))
+                       schedule_work(&adapter->sfp_config_module_task);
+       }
+
        if (eicr & IXGBE_EICR_GPI_SDP1) {
                /* Clear the interrupt */
                IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
-               schedule_work(&adapter->multispeed_fiber_task);
-       } else if (eicr & IXGBE_EICR_GPI_SDP2) {
-               /* Clear the interrupt */
-               IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
-               schedule_work(&adapter->sfp_config_module_task);
-       } else {
-               /* Interrupt isn't for us... */
-               return;
+               if (!test_bit(__IXGBE_DOWN, &adapter->state))
+                       schedule_work(&adapter->multispeed_fiber_task);
        }
 }
 
@@ -3587,6 +3588,14 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
        clear_bit(__IXGBE_DOWN, &adapter->state);
        ixgbe_napi_enable_all(adapter);
 
+       if (ixgbe_is_sfp(hw)) {
+               ixgbe_sfp_link_config(adapter);
+       } else {
+               err = ixgbe_non_sfp_link_config(hw);
+               if (err)
+                       e_err(probe, "link_config FAILED %d\n", err);
+       }
+
        /* clear any pending interrupts, may auto mask */
        IXGBE_READ_REG(hw, IXGBE_EICR);
        ixgbe_irq_enable(adapter, true, true);
@@ -3609,26 +3618,8 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
         * If we're not hot-pluggable SFP+, we just need to configure link
         * and bring it up.
         */
-       if (hw->phy.type == ixgbe_phy_unknown) {
-               err = hw->phy.ops.identify(hw);
-               if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-                       /*
-                        * Take the device down and schedule the sfp tasklet
-                        * which will unregister_netdev and log it.
-                        */
-                       ixgbe_down(adapter);
-                       schedule_work(&adapter->sfp_config_module_task);
-                       return err;
-               }
-       }
-
-       if (ixgbe_is_sfp(hw)) {
-               ixgbe_sfp_link_config(adapter);
-       } else {
-               err = ixgbe_non_sfp_link_config(hw);
-               if (err)
-                       e_err(probe, "link_config FAILED %d\n", err);
-       }
+       if (hw->phy.type == ixgbe_phy_unknown)
+               schedule_work(&adapter->sfp_config_module_task);
 
        /* enable transmits */
        netif_tx_start_all_queues(adapter->netdev);