ixgbe/base: fix X550em SFP+ link stability
authorWenzhuo Lu <wenzhuo.lu@intel.com>
Wed, 24 Jun 2015 03:25:52 +0000 (11:25 +0800)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Fri, 26 Jun 2015 10:58:04 +0000 (12:58 +0200)
Configure the CS4227 correctly for both 1G and 10G operation,
by moving the code to ixgbe_setup_mac_link_sfp_x550em(). It
needs to be in this function because we need both the module
type and the speed, and this is the only function in the init
flow that knows the speed. In contrast,
ixgbe_setup_sfp_modules_X550em() does not know the speed, so we
can't do anything useful here. This is a fundamental difference
from the 82599 flow.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
Acked-by: Helin Zhang <helin.zhang@intel.com>
drivers/net/ixgbe/base/ixgbe_phy.h
drivers/net/ixgbe/base/ixgbe_x550.c

index ffab02e..e3cf7ff 100644 (file)
@@ -93,7 +93,10 @@ POSSIBILITY OF SUCH DAMAGE.
 #define IXGBE_CS4227_GLOBAL_ID_VALUE   0x03E5
 #define IXGBE_CS4227_SCRATCH_VALUE     0x5aa5
 #define IXGBE_CS4227_RETRIES           5
-#define IXGBE_CS4227_SPARE24_LSB       0x12B0  /* Reg to program EDC */
+#define IXGBE_CS4227_LINE_SPARE22_MSB  0x12AD  /* Reg to program speed */
+#define IXGBE_CS4227_LINE_SPARE24_LSB  0x12B0  /* Reg to program EDC */
+#define IXGBE_CS4227_HOST_SPARE22_MSB  0x1AAD  /* Reg to program speed */
+#define IXGBE_CS4227_HOST_SPARE24_LSB  0x1AB0  /* Reg to program EDC */
 #define IXGBE_CS4227_EDC_MODE_CX1      0x0002
 #define IXGBE_CS4227_EDC_MODE_SR       0x0004
 #define IXGBE_CS4227_RESET_HOLD                500     /* microseconds */
index 3c188e9..2e86ea1 100644 (file)
@@ -995,57 +995,12 @@ enum ixgbe_media_type ixgbe_get_media_type_X550em(struct ixgbe_hw *hw)
  */
 s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw)
 {
-       bool setup_linear;
-       u16 reg_slice, edc_mode;
-       s32 ret_val;
-
        DEBUGFUNC("ixgbe_setup_sfp_modules_X550em");
 
-       switch (hw->phy.sfp_type) {
-       case ixgbe_sfp_type_unknown:
-               return IXGBE_SUCCESS;
-       case ixgbe_sfp_type_not_present:
-               return IXGBE_ERR_SFP_NOT_PRESENT;
-       case ixgbe_sfp_type_da_cu_core0:
-       case ixgbe_sfp_type_da_cu_core1:
-               setup_linear = true;
-               break;
-       case ixgbe_sfp_type_srlr_core0:
-       case ixgbe_sfp_type_srlr_core1:
-       case ixgbe_sfp_type_da_act_lmt_core0:
-       case ixgbe_sfp_type_da_act_lmt_core1:
-       case ixgbe_sfp_type_1g_sx_core0:
-       case ixgbe_sfp_type_1g_sx_core1:
-       case ixgbe_sfp_type_1g_lx_core0:
-       case ixgbe_sfp_type_1g_lx_core1:
-               setup_linear = false;
-               break;
-       default:
-               return IXGBE_ERR_SFP_NOT_SUPPORTED;
-       }
-
        ixgbe_init_mac_link_ops_X550em(hw);
        hw->phy.ops.reset = NULL;
 
-       /* The CS4227 slice address is the base address + the port-pair reg
-        * offset. I.e. Slice 0 = 0x12B0 and slice 1 = 0x22B0.
-        */
-       reg_slice = IXGBE_CS4227_SPARE24_LSB + (hw->bus.lan_id << 12);
-
-       if (setup_linear)
-               edc_mode = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
-       else
-               edc_mode = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
-
-       /* Configure CS4227 for connection type. */
-       ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
-                                          edc_mode);
-
-       if (ret_val != IXGBE_SUCCESS)
-               ret_val = ixgbe_write_i2c_combined(hw, 0x80, reg_slice,
-                                                  edc_mode);
-
-       return ret_val;
+       return IXGBE_SUCCESS;
 }
 
 /**
@@ -1346,7 +1301,6 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
  */
 s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
 {
-       struct ixgbe_hic_hdr fw_cmd;
        ixgbe_link_speed link_speed;
        s32 status;
        u32 ctrl = 0;
@@ -1355,22 +1309,6 @@ s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
 
        DEBUGFUNC("ixgbe_reset_hw_X550em");
 
-       fw_cmd.cmd = FW_PHY_MGMT_REQ_CMD;
-       fw_cmd.buf_len = 0;
-       fw_cmd.cmd_or_resp.cmd_resv = 0;
-       fw_cmd.checksum = FW_DEFAULT_CHECKSUM;
-       status = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
-                                             sizeof(fw_cmd),
-                                             IXGBE_HI_PHY_MGMT_REQ_TIMEOUT,
-                                             true);
-       if (status)
-               ERROR_REPORT2(IXGBE_ERROR_CAUTION,
-                             "PHY mgmt command failed with %d\n", status);
-       else if (fw_cmd.cmd_or_resp.ret_status != FW_CEM_RESP_STATUS_SUCCESS)
-               ERROR_REPORT2(IXGBE_ERROR_CAUTION,
-                             "PHY mgmt command returned %d\n",
-                             fw_cmd.cmd_or_resp.ret_status);
-
        /* Call adapter stop to disable Tx/Rx and clear interrupts */
        status = hw->mac.ops.stop_adapter(hw);
        if (status != IXGBE_SUCCESS)
@@ -1708,9 +1646,66 @@ s32 ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw,
                                    ixgbe_link_speed speed,
                                    bool autoneg_wait_to_complete)
 {
+       s32 ret_val;
+       u16 reg_slice, reg_val;
+       bool setup_linear;
        UNREFERENCED_1PARAMETER(autoneg_wait_to_complete);
 
-       return ixgbe_setup_ixfi_x550em(hw, &speed);
+       /* Configure the external PHY. */
+       switch (hw->phy.sfp_type) {
+       case ixgbe_sfp_type_da_cu_core0:
+       case ixgbe_sfp_type_da_cu_core1:
+               setup_linear = true;
+               break;
+       case ixgbe_sfp_type_srlr_core0:
+       case ixgbe_sfp_type_srlr_core1:
+       case ixgbe_sfp_type_da_act_lmt_core0:
+       case ixgbe_sfp_type_da_act_lmt_core1:
+       case ixgbe_sfp_type_1g_sx_core0:
+       case ixgbe_sfp_type_1g_sx_core1:
+#ifdef SUPPORT_1000BASE_LX
+       case ixgbe_sfp_type_1g_lx_core0:
+       case ixgbe_sfp_type_1g_lx_core1:
+#endif /* SUPPORT_1000BASE_LX */
+               setup_linear = false;
+               break;
+       default:
+               return IXGBE_ERR_SFP_NOT_SUPPORTED;
+       }
+
+       /* Configure CS4227 for connection rate. */
+       reg_slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12);
+       reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? 0 : 0x8000;
+       ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+                                          reg_val);
+
+       /* Configure CS4227 for connection type. */
+       reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
+       if (setup_linear)
+               reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+       else
+               reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
+       ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+                                          reg_val);
+
+       reg_slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12);
+       reg_val = (speed & IXGBE_LINK_SPEED_10GB_FULL) ? 0 : 0x8000;
+       ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+                                          reg_val);
+
+       /* Configure CS4227 for connection type. */
+       reg_slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12);
+       if (setup_linear)
+               reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+       else
+               reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
+       ret_val = ixgbe_write_i2c_combined(hw, IXGBE_CS4227, reg_slice,
+                                          reg_val);
+
+       /* Configure the internal PHY. */
+       ret_val = ixgbe_setup_ixfi_x550em(hw, &speed);
+
+       return ret_val;
 }
 
 /**