ixgbe: Remove unnecessary PHY reset, properly identify multispeed fiber modules
authorPJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
Thu, 9 Apr 2009 22:28:15 +0000 (22:28 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 11 Apr 2009 09:48:01 +0000 (02:48 -0700)
This patch does two things:
1) On 82599, the PHY is emedded in the MAC.  On 82598, the SFP+ NIC has an external PHY.  The reset in the SFP+ setup patch for 82598 is unnecessary on 82599, and adds extra dead time to device initialization.  This removes that PHY reset for 82599 only.

2) On 82599, the SFP+ modules are multispeed fiber modules (10G/1G).  We need to make sure to identify them properly for the remaining init sections to properly set them up.

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_82599.c
drivers/net/ixgbe/ixgbe_phy.c
drivers/net/ixgbe/ixgbe_phy.h
drivers/net/ixgbe/ixgbe_type.h

index 9a999898500460529bcc8d0c624eaf21d7f2f2b6..72a0d27a19af4a3ef9b8d976c4ed963a4c1a1c23 100644 (file)
@@ -102,6 +102,9 @@ s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 
        if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
                ixgbe_init_mac_link_ops_82599(hw);
+
+               hw->phy.ops.reset = NULL;
+
                ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
                                                              &data_offset);
 
@@ -716,19 +719,24 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
        /* Call adapter stop to disable tx/rx and clear interrupts */
        hw->mac.ops.stop_adapter(hw);
 
-       /* Reset PHY */
-       if (hw->phy.reset_disable == false) {
-               /* PHY ops must be identified and initialized prior to reset */
+       /* PHY ops must be identified and initialized prior to reset */
 
-               /* Init PHY and function pointers, perform SFP setup */
-               status = hw->phy.ops.init(hw);
+       /* Init PHY and function pointers, perform SFP setup */
+       status = hw->phy.ops.init(hw);
 
-               if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
-                       goto reset_hw_out;
+       if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+               goto reset_hw_out;
 
-               hw->phy.ops.reset(hw);
+       /* Setup SFP module if there is one present. */
+       if (hw->phy.sfp_setup_needed) {
+               status = hw->mac.ops.setup_sfp(hw);
+               hw->phy.sfp_setup_needed = false;
        }
 
+       /* Reset PHY */
+       if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL)
+               hw->phy.ops.reset(hw);
+
        /*
         * Prevent the PCI-E bus from from hanging by disabling PCI-E master
         * access and verify no pending requests before reset
index 14e9606aa3b30a42b734b5f5982cd0842a1370c1..6f11df756daa336faea0eb9f1cf03400f0d4a45f 100644 (file)
@@ -552,6 +552,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
 {
        s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
        u32 vendor_oui = 0;
+       enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
        u8 identifier = 0;
        u8 comp_codes_1g = 0;
        u8 comp_codes_10g = 0;
@@ -620,6 +621,16 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
                                hw->phy.sfp_type = ixgbe_sfp_type_unknown;
                }
 
+               if (hw->phy.sfp_type != stored_sfp_type)
+                       hw->phy.sfp_setup_needed = true;
+
+               /* Determine if the SFP+ PHY is dual speed or not. */
+               if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
+                  (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) ||
+                  ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) &&
+                  (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)))
+                       hw->phy.multispeed_fiber = true;
+
                /* Determine PHY vendor */
                if (hw->phy.type == ixgbe_phy_unknown) {
                        hw->phy.id = identifier;
index cc5f1b3287e18c4e8c28a058f2f1fe895e635f5f..c9964b7ce1b991de03c0c257799756794c06a336 100644 (file)
@@ -44,6 +44,7 @@
 /* Bitmasks */
 #define IXGBE_SFF_TWIN_AX_CAPABLE            0x80
 #define IXGBE_SFF_1GBASESX_CAPABLE           0x1
+#define IXGBE_SFF_1GBASELX_CAPABLE           0x2
 #define IXGBE_SFF_10GBASESR_CAPABLE          0x10
 #define IXGBE_SFF_10GBASELR_CAPABLE          0x20
 #define IXGBE_I2C_EEPROM_READ_MASK           0x100
index 06d7e8ae62251340cc6467d764516b5ec8cb8213..db65c05773ad6504963db55dea8e2b84747f0b7f 100644 (file)
@@ -2198,6 +2198,7 @@ struct ixgbe_phy_info {
        u32                             addr;
        u32                             id;
        enum ixgbe_sfp_type             sfp_type;
+       bool                            sfp_setup_needed;
        u32                             revision;
        enum ixgbe_media_type           media_type;
        bool                            reset_disable;