ixgbe: fix 82598 SFP initialization after driver load.
authorDon Skidmore <donald.c.skidmore@intel.com>
Wed, 27 May 2009 03:40:47 +0000 (20:40 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 27 May 2009 03:40:47 +0000 (20:40 -0700)
If we loaded the driver with out a SFP module plugged in it would
leave it in a state that make it later unable to link when a module
was plugged in.  This patch corrects that by:

ixgbe_probe() - moving the check for IXGBE_ERR_SFP_NOT_PRESENT from
after get_invariants() to after reset_hw() as now reset_hw() is
where this condition will be indentified.

ixgbe_reset_hw_82598() - Enable this function to now return
IXGBE_ERR_SFP_NOT_PRESENT.

ixgbe_identify_sfp_module_generic() - This where the lack of SFP
module is detected.  Modifications are added to allow a different
return value for modules that just haven't been plugged in yet.

Other functions were updated to allow correct logging.

Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ixgbe/ixgbe_82598.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/ixgbe/ixgbe_phy.c

index afc9fe3f1eda8274090828095e6ad394e336e9d5..88e8350aa78614da106a206c9587f0d77337268e 100644 (file)
@@ -698,6 +698,7 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
 static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
 {
        s32 status = 0;
+       s32 phy_status = 0;
        u32 ctrl;
        u32 gheccr;
        u32 i;
@@ -745,13 +746,17 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
                /* PHY ops must be identified and initialized prior to reset */
 
                /* Init PHY and function pointers, perform SFP setup */
-               status = hw->phy.ops.init(hw);
-               if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+               phy_status = hw->phy.ops.init(hw);
+               if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
                        goto reset_hw_out;
+               else if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
+                       goto no_phy_reset;
+
 
                hw->phy.ops.reset(hw);
        }
 
+no_phy_reset:
        /*
         * Prevent the PCI-E bus from from hanging by disabling PCI-E master
         * access and verify no pending requests before reset
@@ -811,6 +816,9 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
        hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
 
 reset_hw_out:
+       if (phy_status)
+               status = phy_status;
+
        return status;
 }
 
index e52798c4816b0837bd1729c59a88d418865c9466..f9223acae30b9d31d688f40e103a727ca0f474fe 100644 (file)
@@ -2599,7 +2599,10 @@ int ixgbe_up(struct ixgbe_adapter *adapter)
 void ixgbe_reset(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       if (hw->mac.ops.init_hw(hw))
+       int err;
+
+       err = hw->mac.ops.init_hw(hw);
+       if (err && (err != IXGBE_ERR_SFP_NOT_PRESENT))
                dev_err(&adapter->pdev->dev, "Hardware Error\n");
 
        /* reprogram the RAR[0] in case user changed it. */
@@ -5167,20 +5170,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        INIT_WORK(&adapter->sfp_config_module_task,
                  ixgbe_sfp_config_module_task);
 
-       err = ii->get_invariants(hw);
-       if (err == IXGBE_ERR_SFP_NOT_PRESENT) {
-               /* start a kernel thread to watch for a module to arrive */
-               set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
-               mod_timer(&adapter->sfp_timer,
-                         round_jiffies(jiffies + (2 * HZ)));
-               err = 0;
-       } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-               DPRINTK(PROBE, ERR, "failed to load because an "
-                       "unsupported SFP+ module type was detected.\n");
-               goto err_hw_init;
-       } else if (err) {
-               goto err_hw_init;
-       }
+       ii->get_invariants(hw);
 
        /* setup the private structure */
        err = ixgbe_sw_init(adapter);
@@ -5200,7 +5190,18 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 
        /* reset_hw fills in the perm_addr as well */
        err = hw->mac.ops.reset_hw(hw);
-       if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+       if (err == IXGBE_ERR_SFP_NOT_PRESENT &&
+           hw->mac.type == ixgbe_mac_82598EB) {
+               /*
+                * Start a kernel thread to watch for a module to arrive.
+                * Only do this for 82598, since 82599 will generate
+                * interrupts on module arrival.
+                */
+               set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
+               mod_timer(&adapter->sfp_timer,
+                         round_jiffies(jiffies + (2 * HZ)));
+               err = 0;
+       } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
                dev_err(&adapter->pdev->dev, "failed to load because an "
                        "unsupported SFP+ module type was detected.\n");
                goto err_sw_init;
index 8210b49aeff41ce2b4af703a811e30a9d3979fa3..e43d6248d7d4958e912347a654f83d27976c0f2e 100644 (file)
@@ -530,11 +530,22 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
        u8 cable_tech = 0;
        u16 enforce_sfp = 0;
 
+       if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) {
+               hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+               status = IXGBE_ERR_SFP_NOT_PRESENT;
+               goto out;
+       }
+
        status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
                                             &identifier);
 
-       if (status == IXGBE_ERR_SFP_NOT_PRESENT) {
+       if (status == IXGBE_ERR_SFP_NOT_PRESENT || status == IXGBE_ERR_I2C) {
+               status = IXGBE_ERR_SFP_NOT_PRESENT;
                hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+               if (hw->phy.type != ixgbe_phy_nl) {
+                       hw->phy.id = 0;
+                       hw->phy.type = ixgbe_phy_unknown;
+               }
                goto out;
        }