ixgbe: Fix flow control for Xeon D KR backplane
authorMark Rustad <mark.d.rustad@intel.com>
Tue, 26 Jan 2016 00:32:10 +0000 (16:32 -0800)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Tue, 5 Apr 2016 00:44:31 +0000 (17:44 -0700)
Xeon D KR backplane is different from other backplanes,
in that we can't use auto-negotiation to determine the
mode. Instead, use whatever the user configured.

Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c

index 9790d0274f7feac08395e34172a05ca598ae0a67..f47eb12a9c50332ff00afc0791e7518f8756d8c8 100644 (file)
@@ -1192,6 +1192,7 @@ static const struct ixgbe_mac_operations mac_ops_82598 = {
        .clear_vfta             = &ixgbe_clear_vfta_82598,
        .set_vfta               = &ixgbe_set_vfta_82598,
        .fc_enable              = &ixgbe_fc_enable_82598,
+       .setup_fc               = ixgbe_setup_fc_generic,
        .set_fw_drv_ver         = NULL,
        .acquire_swfw_sync      = &ixgbe_acquire_swfw_sync,
        .release_swfw_sync      = &ixgbe_release_swfw_sync,
index b276fe0bc66531ad74fc31ec5b64d0f036598cff..c3ae5a701d4307b91f5f942624cc60e0ea5e169e 100644 (file)
@@ -2220,6 +2220,7 @@ static const struct ixgbe_mac_operations mac_ops_82599 = {
        .clear_vfta             = &ixgbe_clear_vfta_generic,
        .set_vfta               = &ixgbe_set_vfta_generic,
        .fc_enable              = &ixgbe_fc_enable_generic,
+       .setup_fc               = ixgbe_setup_fc_generic,
        .set_fw_drv_ver         = &ixgbe_set_fw_drv_ver_generic,
        .init_uta_tables        = &ixgbe_init_uta_tables_generic,
        .setup_sfp              = &ixgbe_setup_sfp_modules_82599,
index 64045053e874b8a7b1eb27333ef8a2bd4835700c..8c7e78b21c4e2198d4045ca0331480dce96fa538 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2015 Intel Corporation.
+  Copyright(c) 1999 - 2016 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -111,12 +111,12 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
 }
 
 /**
- *  ixgbe_setup_fc - Set up flow control
+ *  ixgbe_setup_fc_generic - Set up flow control
  *  @hw: pointer to hardware structure
  *
  *  Called at init time to set up flow control.
  **/
-static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
+s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw)
 {
        s32 ret_val = 0;
        u32 reg = 0, reg_bp = 0;
@@ -296,7 +296,7 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
        IXGBE_WRITE_FLUSH(hw);
 
        /* Setup flow control */
-       ret_val = ixgbe_setup_fc(hw);
+       ret_val = hw->mac.ops.setup_fc(hw);
        if (ret_val)
                return ret_val;
 
index 2b9563137fd88f932053a9a867754fd2328d31c1..2e290150ab541fe57833e8f165344bc764baa83e 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2014 Intel Corporation.
+  Copyright(c) 1999 - 2016 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -81,6 +81,7 @@ s32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw);
 s32 ixgbe_enable_rx_buff_generic(struct ixgbe_hw *hw);
 s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
 s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw);
+s32 ixgbe_setup_fc_generic(struct ixgbe_hw *);
 bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
 void ixgbe_fc_autoneg(struct ixgbe_hw *hw);
 
index 29e0b0e1cb67a71aea5a58930f4ef8b2dfb46199..787d2b21465e8e28ccb267c6e48a6ef099cad849 100644 (file)
@@ -3308,6 +3308,7 @@ struct ixgbe_mac_operations {
 
        /* Flow Control */
        s32 (*fc_enable)(struct ixgbe_hw *);
+       s32 (*setup_fc)(struct ixgbe_hw *);
 
        /* Manageability interface */
        s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8);
@@ -3525,6 +3526,7 @@ struct ixgbe_info {
 
 #define IXGBE_KRM_PORT_CAR_GEN_CTRL(P) ((P) ? 0x8010 : 0x4010)
 #define IXGBE_KRM_LINK_CTRL_1(P)       ((P) ? 0x820C : 0x420C)
+#define IXGBE_KRM_AN_CNTL_1(P)         ((P) ? 0x822C : 0x422C)
 #define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634)
 #define IXGBE_KRM_DSP_TXFFE_STATE_5(P) ((P) ? 0x8638 : 0x4638)
 #define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P)        ((P) ? 0x8B00 : 0x4B00)
@@ -3547,6 +3549,9 @@ struct ixgbe_info {
 #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE           (1 << 29)
 #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART          (1 << 31)
 
+#define IXGBE_KRM_AN_CNTL_1_SYM_PAUSE                  (1 << 28)
+#define IXGBE_KRM_AN_CNTL_1_ASM_PAUSE                  (1 << 29)
+
 #define IXGBE_KRM_DSP_TXFFE_STATE_C0_EN                        (1 << 6)
 #define IXGBE_KRM_DSP_TXFFE_STATE_CP1_CN1_EN           (1 << 15)
 #define IXGBE_KRM_DSP_TXFFE_STATE_CO_ADAPT_EN          (1 << 16)
index 0d69564f3a1b2c646d0208dd4666df029b835790..c00b67b4c1dcd22fcedda4061344068041024d6e 100644 (file)
@@ -846,6 +846,7 @@ static const struct ixgbe_mac_operations mac_ops_X540 = {
        .clear_vfta             = &ixgbe_clear_vfta_generic,
        .set_vfta               = &ixgbe_set_vfta_generic,
        .fc_enable              = &ixgbe_fc_enable_generic,
+       .setup_fc               = ixgbe_setup_fc_generic,
        .set_fw_drv_ver         = &ixgbe_set_fw_drv_ver_generic,
        .init_uta_tables        = &ixgbe_init_uta_tables_generic,
        .setup_sfp              = NULL,
index 26e0b8df2afea93eb97ff5ef92cabd2bde727783..972c9aa175032fcc25a1a0903a89813bbd792269 100644 (file)
@@ -27,6 +27,7 @@
 #include "ixgbe_phy.h"
 
 static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed);
+static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *);
 
 static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw)
 {
@@ -1342,15 +1343,18 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
                mac->ops.enable_tx_laser = NULL;
                mac->ops.flap_tx_laser = NULL;
                mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber;
+               mac->ops.setup_fc = ixgbe_setup_fc_x550em;
                mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_x550em;
                mac->ops.set_rate_select_speed =
                                        ixgbe_set_soft_rate_select_speed;
                break;
        case ixgbe_media_type_copper:
                mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em;
+               mac->ops.setup_fc = ixgbe_setup_fc_generic;
                mac->ops.check_link = ixgbe_check_link_t_X550em;
                break;
        default:
+               mac->ops.setup_fc = ixgbe_setup_fc_x550em;
                break;
        }
 }
@@ -1842,6 +1846,82 @@ static s32 ixgbe_get_lcd_t_x550em(struct ixgbe_hw *hw,
        return status;
 }
 
+/**
+ * ixgbe_setup_fc_x550em - Set up flow control
+ * @hw: pointer to hardware structure
+ */
+static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *hw)
+{
+       bool pause, asm_dir;
+       u32 reg_val;
+       s32 rc;
+
+       /* Validate the requested mode */
+       if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
+               hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
+               return IXGBE_ERR_INVALID_LINK_SETTINGS;
+       }
+
+       /* 10gig parts do not have a word in the EEPROM to determine the
+        * default flow control setting, so we explicitly set it to full.
+        */
+       if (hw->fc.requested_mode == ixgbe_fc_default)
+               hw->fc.requested_mode = ixgbe_fc_full;
+
+       /* Determine PAUSE and ASM_DIR bits. */
+       switch (hw->fc.requested_mode) {
+       case ixgbe_fc_none:
+               pause = false;
+               asm_dir = false;
+               break;
+       case ixgbe_fc_tx_pause:
+               pause = false;
+               asm_dir = true;
+               break;
+       case ixgbe_fc_rx_pause:
+               /* Rx Flow control is enabled and Tx Flow control is
+                * disabled by software override. Since there really
+                * isn't a way to advertise that we are capable of RX
+                * Pause ONLY, we will advertise that we support both
+                * symmetric and asymmetric Rx PAUSE, as such we fall
+                * through to the fc_full statement.  Later, we will
+                * disable the adapter's ability to send PAUSE frames.
+                */
+               /* Fallthrough */
+       case ixgbe_fc_full:
+               pause = true;
+               asm_dir = true;
+               break;
+       default:
+               hw_err(hw, "Flow control param set incorrectly\n");
+               return IXGBE_ERR_CONFIG;
+       }
+
+       if (hw->device_id != IXGBE_DEV_ID_X550EM_X_KR)
+               return 0;
+
+       rc = ixgbe_read_iosf_sb_reg_x550(hw,
+                                        IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+                                        IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+       if (rc)
+               return rc;
+
+       reg_val &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
+                    IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
+       if (pause)
+               reg_val |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
+       if (asm_dir)
+               reg_val |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
+       rc = ixgbe_write_iosf_sb_reg_x550(hw,
+                                         IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+                                         IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+
+       /* This device does not fully support AN. */
+       hw->fc.disable_fc_autoneg = true;
+
+       return rc;
+}
+
 /** ixgbe_enter_lplu_x550em - Transition to low power states
  *  @hw: pointer to hardware structure
  *
@@ -2337,8 +2417,6 @@ static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask)
        .enable_rx_buff                 = &ixgbe_enable_rx_buff_generic, \
        .get_thermal_sensor_data        = NULL, \
        .init_thermal_sensor_thresh     = NULL, \
-       .prot_autoc_read                = &prot_autoc_read_generic, \
-       .prot_autoc_write               = &prot_autoc_write_generic, \
        .enable_rx                      = &ixgbe_enable_rx_generic, \
        .disable_rx                     = &ixgbe_disable_rx_x550, \
 
@@ -2354,6 +2432,9 @@ static const struct ixgbe_mac_operations mac_ops_X550 = {
        .setup_sfp              = NULL,
        .acquire_swfw_sync      = &ixgbe_acquire_swfw_sync_X540,
        .release_swfw_sync      = &ixgbe_release_swfw_sync_X540,
+       .prot_autoc_read        = prot_autoc_read_generic,
+       .prot_autoc_write       = prot_autoc_write_generic,
+       .setup_fc               = ixgbe_setup_fc_generic,
 };
 
 static const struct ixgbe_mac_operations mac_ops_X550EM_x = {
@@ -2368,6 +2449,7 @@ static const struct ixgbe_mac_operations mac_ops_X550EM_x = {
        .setup_sfp              = ixgbe_setup_sfp_modules_X550em,
        .acquire_swfw_sync      = &ixgbe_acquire_swfw_sync_X550em,
        .release_swfw_sync      = &ixgbe_release_swfw_sync_X550em,
+       .setup_fc               = NULL, /* defined later */
 };
 
 #define X550_COMMON_EEP \