Print this page
4431 igb support for I354
4616 igb has uninitialized kstats

@@ -142,10 +142,11 @@
                 reg = E1000_READ_REG(hw, E1000_MDIC);
                 ext_mdio = !!(reg & E1000_MDIC_DEST);
                 break;
         case e1000_82580:
         case e1000_i350:
+        case e1000_i354:
         case e1000_i210:
         case e1000_i211:
                 reg = E1000_READ_REG(hw, E1000_MDICNFG);
                 ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO);
                 break;

@@ -205,10 +206,11 @@
                 phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575;
         } else {
                 switch (hw->mac.type) {
                 case e1000_82580:
                 case e1000_i350:
+                case e1000_i354:
                         phy->ops.read_reg = e1000_read_phy_reg_82580;
                         phy->ops.write_reg = e1000_write_phy_reg_82580;
                         break;
                 case e1000_i210:
                 case e1000_i211:

@@ -224,24 +226,30 @@
         /* Set phy->phy_addr and phy->id. */
         ret_val = e1000_get_phy_id_82575(hw);
 
         /* Verify phy id and set remaining function pointers */
         switch (phy->id) {
+        case M88E1543_E_PHY_ID:
+        case M88E1512_E_PHY_ID:
         case I347AT4_E_PHY_ID:
         case M88E1112_E_PHY_ID:
         case M88E1340M_E_PHY_ID:
         case M88E1111_I_PHY_ID:
                 phy->type               = e1000_phy_m88;
                 phy->ops.check_polarity = e1000_check_polarity_m88;
                 phy->ops.get_info       = e1000_get_phy_info_m88;
-                if (phy->id == I347AT4_E_PHY_ID ||
-                    phy->id == M88E1112_E_PHY_ID ||
-                    phy->id == M88E1340M_E_PHY_ID)
+                switch (phy->id) {
+                case I347AT4_E_PHY_ID:
+                case M88E1112_E_PHY_ID:
+                case M88E1340M_E_PHY_ID:
+                case M88E1543_E_PHY_ID:
+                case M88E1512_E_PHY_ID:
                         phy->ops.get_cable_length =
                                          e1000_get_cable_length_m88_gen2;
-                else
+                default:
                         phy->ops.get_cable_length = e1000_get_cable_length_m88;
+                }
                 phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
                 break;
         case IGP03E1000_E_PHY_ID:
         case IGP04E1000_E_PHY_ID:
                 phy->type = e1000_phy_igp_3;

@@ -353,10 +361,11 @@
         case e1000_82580:
                 nvm->ops.validate = e1000_validate_nvm_checksum_82580;
                 nvm->ops.update = e1000_update_nvm_checksum_82580;
                 break;
         case e1000_i350:
+        case e1000_i354:
                 nvm->ops.validate = e1000_validate_nvm_checksum_i350;
                 nvm->ops.update = e1000_update_nvm_checksum_i350;
                 break;
         default:
                 break;

@@ -386,14 +395,14 @@
         mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
         if (mac->type == e1000_82576)
                 mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
         if (mac->type == e1000_82580)
                 mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
-        if (mac->type == e1000_i350)
+        if (mac->type == e1000_i350 || mac->type == e1000_i354)
                 mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
 
-        /* Enable EEE default settings for EEE supported devices */
+        /* Disable EEE default settings for EEE supported devices */
         if (mac->type >= e1000_i350)
                 dev_spec->eee_disable = TRUE;
 
         /* Allow a single clear of the SW semaphore on I210 and newer */
         if (mac->type >= e1000_i210)

@@ -434,11 +443,11 @@
         mac->ops.read_mac_addr = e1000_read_mac_addr_82575;
         /* configure collision distance */
         mac->ops.config_collision_dist = e1000_config_collision_dist_82575;
         /* multicast address update */
         mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
-        if (mac->type == e1000_i350) {
+        if (mac->type == e1000_i350 || mac->type == e1000_i354) {
                 /* writing VFTA */
                 mac->ops.write_vfta = e1000_write_vfta_i350;
                 /* clearing VFTA */
                 mac->ops.clear_vfta = e1000_clear_vfta_i350;
         } else {

@@ -620,10 +629,14 @@
         u32 ctrl_ext;
         u32 mdic;
 
         DEBUGFUNC("e1000_get_phy_id_82575");
 
+        /* some i354 devices need an extra read for phy id */
+        if (hw->mac.type == e1000_i354)
+                e1000_get_phy_id(hw);
+
         /*
          * For SGMII PHYs, we try the list of possible addresses until
          * we find one that works.  For non-SGMII PHYs
          * (e.g. integrated copper PHYs), an address of 1 should
          * work.  The result of this function should mean phy->phy_addr

@@ -643,10 +656,11 @@
                         mdic &= E1000_MDIC_PHY_MASK;
                         phy->addr = mdic >> E1000_MDIC_PHY_SHIFT;
                         break;
                 case e1000_82580:
                 case e1000_i350:
+                case e1000_i354:
                 case e1000_i210:
                 case e1000_i211:
                         mdic = E1000_READ_REG(hw, E1000_MDICNFG);
                         mdic &= E1000_MDICNFG_PHY_MASK;
                         phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT;

@@ -1213,10 +1227,11 @@
 static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
                                                 u16 *speed, u16 *duplex)
 {
         struct e1000_mac_info *mac = &hw->mac;
         u32 pcs;
+        u32 status;
 
         DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575");
 
         /*
          * Read the PCS Status register for link state. For non-copper mode,

@@ -1243,10 +1258,22 @@
                 if (pcs & E1000_PCS_LSTS_DUPLEX_FULL)
                         *duplex = FULL_DUPLEX;
                 else
                         *duplex = HALF_DUPLEX;
 
+                /* Check if it is an I354 2.5Gb backplane connection. */
+                if (mac->type == e1000_i354) {
+                        status = E1000_READ_REG(hw, E1000_STATUS);
+                        if ((status & E1000_STATUS_2P5_SKU) &&
+                            !(status & E1000_STATUS_2P5_SKU_OVER)) {
+                                *speed = SPEED_2500;
+                                *duplex = FULL_DUPLEX;
+                                DEBUGOUT("2500 Mbs, ");
+                                DEBUGOUT("Full Duplex\n");
+                        }
+                }
+
         } else {
                 mac->serdes_has_link = FALSE;
                 *speed = 0;
                 *duplex = 0;
         }

@@ -1428,15 +1455,22 @@
         ctrl = E1000_READ_REG(hw, E1000_CTRL);
         ctrl |= E1000_CTRL_SLU;
         ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
         E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
 
-        /* Clear Go Link Disconnect bit */
-        if (hw->mac.type >= e1000_82580) {
+        /* Clear Go Link Disconnect bit on supported devices */
+        switch (hw->mac.type) {
+        case e1000_82580:
+        case e1000_i350:
+        case e1000_i210:
+        case e1000_i211:
                 phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
                 phpm_reg &= ~E1000_82580_PM_GO_LINKD;
                 E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg);
+                break;
+        default:
+                break;
         }
 
         ret_val = e1000_setup_serdes_link_82575(hw);
         if (ret_val)
                 goto out;

@@ -2130,46 +2164,36 @@
  *
  *  enables/disables L2 switch anti-spoofing functionality.
  **/
 void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
 {
-        u32 dtxswc;
+        u32 reg_val, reg_offset;
 
         switch (hw->mac.type) {
         case e1000_82576:
-                dtxswc = E1000_READ_REG(hw, E1000_DTXSWC);
-                if (enable) {
-                        dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
-                                   E1000_DTXSWC_VLAN_SPOOF_MASK);
-                        /* The PF can spoof - it has to in order to
-                         * support emulation mode NICs */
-                        dtxswc ^= (1 << pf | 1 << (pf +
-                                   E1000_DTXSWC_VLAN_SPOOF_SHIFT));
-                } else {
-                        dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
-                                    E1000_DTXSWC_VLAN_SPOOF_MASK);
-                }
-                E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
+                reg_offset = E1000_DTXSWC;
                 break;
         case e1000_i350:
-                dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
+        case e1000_i354:
+                reg_offset = E1000_TXSWC;
+                break;
+        default:
+                return;
+        }
+        reg_val = E1000_READ_REG(hw, reg_offset);
                 if (enable) {
-                        dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
+                reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK |
                                    E1000_DTXSWC_VLAN_SPOOF_MASK);
                         /* The PF can spoof - it has to in order to
                          * support emulation mode NICs
                          */
-                        dtxswc ^= (1 << pf | 1 << (pf +
-                                   E1000_DTXSWC_VLAN_SPOOF_SHIFT));
+                reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS));
                 } else {
-                        dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
+                reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
                                     E1000_DTXSWC_VLAN_SPOOF_MASK);
                 }
-                E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc);
-        default:
-                break;
-        }
+        E1000_WRITE_REG(hw, reg_offset, reg_val);
 }
 
 /**
  *  e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback
  *  @hw: pointer to the hardware struct

@@ -2189,10 +2213,11 @@
                 else
                         dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
                 E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
                 break;
         case e1000_i350:
+        case e1000_i354:
                 dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
                 if (enable)
                         dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
                 else
                         dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;

@@ -2686,10 +2711,118 @@
         E1000_READ_REG(hw, E1000_EEER);
 out:
 
         return ret_val;
 }
+
+/**
+ *  e1000_set_eee_i354 - Enable/disable EEE support
+ *  @hw: pointer to the HW structure
+ *
+ *  Enable/disable EEE legacy mode based on setting in dev_spec structure.
+ *
+ **/
+s32 e1000_set_eee_i354(struct e1000_hw *hw)
+{
+        struct e1000_phy_info *phy = &hw->phy;
+        s32 ret_val = E1000_SUCCESS;
+        u16 phy_data;
+
+        DEBUGFUNC("e1000_set_eee_i354");
+
+        if ((hw->phy.media_type != e1000_media_type_copper) ||
+            ((phy->id != M88E1543_E_PHY_ID) &&
+            (phy->id != M88E1512_E_PHY_ID)))
+                goto out;
+
+        if (!hw->dev_spec._82575.eee_disable) {
+                /* Switch to PHY page 18. */
+                ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 18);
+                if (ret_val)
+                        goto out;
+
+                ret_val = phy->ops.read_reg(hw, E1000_M88E1543_EEE_CTRL_1,
+                                            &phy_data);
+                if (ret_val)
+                        goto out;
+
+                phy_data |= E1000_M88E1543_EEE_CTRL_1_MS;
+                ret_val = phy->ops.write_reg(hw, E1000_M88E1543_EEE_CTRL_1,
+                                             phy_data);
+                if (ret_val)
+                        goto out;
+
+                /* Return the PHY to page 0. */
+                ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0);
+                if (ret_val)
+                        goto out;
+
+                /* Turn on EEE advertisement. */
+                ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
+                                               E1000_EEE_ADV_DEV_I354,
+                                               &phy_data);
+                if (ret_val)
+                        goto out;
+
+                phy_data |= E1000_EEE_ADV_100_SUPPORTED |
+                            E1000_EEE_ADV_1000_SUPPORTED;
+                ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
+                                                E1000_EEE_ADV_DEV_I354,
+                                                phy_data);
+        } else {
+                /* Turn off EEE advertisement. */
+                ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
+                                               E1000_EEE_ADV_DEV_I354,
+                                               &phy_data);
+                if (ret_val)
+                        goto out;
+
+                phy_data &= ~(E1000_EEE_ADV_100_SUPPORTED |
+                              E1000_EEE_ADV_1000_SUPPORTED);
+                ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
+                                                E1000_EEE_ADV_DEV_I354,
+                                                phy_data);
+        }
+
+out:
+        return ret_val;
+}
+
+/**
+ *  e1000_get_eee_status_i354 - Get EEE status
+ *  @hw: pointer to the HW structure
+ *  @status: EEE status
+ *
+ *  Get EEE status by guessing based on whether Tx or Rx LPI indications have
+ *  been received.
+ **/
+s32 e1000_get_eee_status_i354(struct e1000_hw *hw, bool *status)
+{
+        struct e1000_phy_info *phy = &hw->phy;
+        s32 ret_val = E1000_SUCCESS;
+        u16 phy_data;
+
+        DEBUGFUNC("e1000_get_eee_status_i354");
+
+        /* Check if EEE is supported on this device. */
+        if ((hw->phy.media_type != e1000_media_type_copper) ||
+            ((phy->id != M88E1543_E_PHY_ID) &&
+             (phy->id != M88E1512_E_PHY_ID)))
+                goto out;
+
+        ret_val = e1000_read_xmdio_reg(hw, E1000_PCS_STATUS_ADDR_I354,
+                                       E1000_PCS_STATUS_DEV_I354,
+                                       &phy_data);
+        if (ret_val)
+                goto out;
+
+        *status = phy_data & (E1000_PCS_STATUS_TX_LPI_RCVD |
+                              E1000_PCS_STATUS_RX_LPI_RCVD) ? TRUE : FALSE;
+
+out:
+        return ret_val;
+}
 
 /* Due to a hw errata, if the host tries to  configure the VFTA register
  * while performing queries from the BMC or DMA, then the VFTA in some
  * cases won't be written.
  */