Author: marius
Date: Thu Aug 31 23:59:46 2017
New Revision: 323080
URL: https://svnweb.freebsd.org/changeset/base/323080

Log:
  MFC: r308643, r312427, r312641, r322986
  
  - Update WOL support for newer em(4) devices. [1]
  - Add support for Kaby Lake generation i219 (4) and i219 (5) devices.
  - Enable WOL features also for the igb(4) class of devices. [1]
  - Don't set any WOL enabling hardware bits if WOL isn't requested
    according to the enabled interface capability bits.
  
  PR:           208343 [1]
  Submitted by: Kaho Tashikazu <k...@elam.kais.kyoto-u.ac.jp> [1]
  Approved by:  re (kib)

Modified:
  stable/10/sys/dev/e1000/e1000_82575.c
  stable/10/sys/dev/e1000/e1000_82575.h
  stable/10/sys/dev/e1000/e1000_defines.h
  stable/10/sys/dev/e1000/e1000_ich8lan.c
  stable/10/sys/dev/e1000/if_em.c
  stable/10/sys/dev/e1000/if_igb.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/e1000/e1000_82575.c
==============================================================================
--- stable/10/sys/dev/e1000/e1000_82575.c       Thu Aug 31 23:57:34 2017        
(r323079)
+++ stable/10/sys/dev/e1000/e1000_82575.c       Thu Aug 31 23:59:46 2017        
(r323080)
@@ -101,7 +101,6 @@ static s32 e1000_validate_nvm_checksum_with_offset(str
                                                   u16 offset);
 static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw);
 static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw);
-static void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value);
 static void e1000_clear_vfta_i350(struct e1000_hw *hw);
 
 static void e1000_i2c_start(struct e1000_hw *hw);

Modified: stable/10/sys/dev/e1000/e1000_82575.h
==============================================================================
--- stable/10/sys/dev/e1000/e1000_82575.h       Thu Aug 31 23:57:34 2017        
(r323079)
+++ stable/10/sys/dev/e1000/e1000_82575.h       Thu Aug 31 23:59:46 2017        
(r323080)
@@ -493,6 +493,7 @@ enum e1000_promisc_type {
 void e1000_vfta_set_vf(struct e1000_hw *, u16, bool);
 void e1000_rlpml_set_vf(struct e1000_hw *, u16);
 s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type);
+void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value);
 u16 e1000_rxpbs_adjust_82580(u32 data);
 s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data);
 s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M);

Modified: stable/10/sys/dev/e1000/e1000_defines.h
==============================================================================
--- stable/10/sys/dev/e1000/e1000_defines.h     Thu Aug 31 23:57:34 2017        
(r323079)
+++ stable/10/sys/dev/e1000/e1000_defines.h     Thu Aug 31 23:59:46 2017        
(r323080)
@@ -469,6 +469,8 @@
 
 #define ETHERNET_FCS_SIZE              4
 #define MAX_JUMBO_FRAME_SIZE           0x3F00
+/* The datasheet maximum supported RX size is 9.5KB (9728 bytes) */
+#define MAX_RX_JUMBO_FRAME_SIZE                0x2600
 #define E1000_TX_PTR_GAP               0x1F
 
 /* Extended Configuration Control and Size */

Modified: stable/10/sys/dev/e1000/e1000_ich8lan.c
==============================================================================
--- stable/10/sys/dev/e1000/e1000_ich8lan.c     Thu Aug 31 23:57:34 2017        
(r323079)
+++ stable/10/sys/dev/e1000/e1000_ich8lan.c     Thu Aug 31 23:59:46 2017        
(r323080)
@@ -243,8 +243,7 @@ static bool e1000_phy_is_accessible_pchlan(struct e100
        if (ret_val)
                return FALSE;
 out:
-       if ((hw->mac.type == e1000_pch_lpt) ||
-           (hw->mac.type == e1000_pch_spt)) {
+       if (hw->mac.type >= e1000_pch_lpt) {
                /* Only unforce SMBus if ME is not active */
                if (!(E1000_READ_REG(hw, E1000_FWSM) &
                    E1000_ICH_FWSM_FW_VALID)) {
@@ -641,7 +640,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_
 
        nvm->type = e1000_nvm_flash_sw;
 
-       if (hw->mac.type == e1000_pch_spt) {
+       if (hw->mac.type >= e1000_pch_spt) {
                /* in SPT, gfpreg doesn't exist. NVM size is taken from the
                 * STRAP register. This is because in SPT the GbE Flash region
                 * is no longer accessed through the flash registers. Instead,
@@ -701,7 +700,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_
        /* Function Pointers */
        nvm->ops.acquire        = e1000_acquire_nvm_ich8lan;
        nvm->ops.release        = e1000_release_nvm_ich8lan;
-       if (hw->mac.type == e1000_pch_spt) {
+       if (hw->mac.type >= e1000_pch_spt) {
                nvm->ops.read   = e1000_read_nvm_spt;
                nvm->ops.update = e1000_update_nvm_checksum_spt;
        } else {
@@ -815,8 +814,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_
                break;
        }
 
-       if ((mac->type == e1000_pch_lpt) ||
-           (mac->type == e1000_pch_spt)) {
+       if (mac->type >= e1000_pch_lpt) {
                mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
                mac->ops.rar_set = e1000_rar_set_pch_lpt;
                mac->ops.setup_physical_interface = 
e1000_setup_copper_link_pch_lpt;
@@ -1576,9 +1574,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct 
         * aggressive resulting in many collisions. To avoid this, increase
         * the IPG and reduce Rx latency in the PHY.
         */
-       if (((hw->mac.type == e1000_pch2lan) ||
-            (hw->mac.type == e1000_pch_lpt) ||
-            (hw->mac.type == e1000_pch_spt)) && link) {
+       if ((hw->mac.type >= e1000_pch2lan) && link) {
                u16 speed, duplex;
 
                e1000_get_speed_and_duplex_copper_generic(hw, &speed, &duplex);
@@ -1589,7 +1585,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct 
                        tipg_reg |= 0xFF;
                        /* Reduce Rx latency in analog PHY */
                        emi_val = 0;
-               } else if (hw->mac.type == e1000_pch_spt &&
+               } else if (hw->mac.type >= e1000_pch_spt &&
                           duplex == FULL_DUPLEX && speed != SPEED_1000) {
                        tipg_reg |= 0xC;
                        emi_val = 1;
@@ -1611,8 +1607,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct 
                        emi_addr = I217_RX_CONFIG;
                ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val);
 
-               if (hw->mac.type == e1000_pch_lpt ||
-                   hw->mac.type == e1000_pch_spt) {
+
+               if (hw->mac.type >= e1000_pch_lpt) {
                        u16 phy_reg;
 
                        hw->phy.ops.read_reg_locked(hw, I217_PLL_CLOCK_GATE_REG,
@@ -1641,7 +1637,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct 
                if (ret_val)
                        return ret_val;
 
-               if (hw->mac.type == e1000_pch_spt) {
+               if (hw->mac.type >= e1000_pch_spt) {
                        u16 data;
                        u16 ptr_gap;
 
@@ -1690,8 +1686,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct 
         * on power up.
         * Set the Beacon Duration for I217 to 8 usec
         */
-       if ((hw->mac.type == e1000_pch_lpt) ||
-           (hw->mac.type == e1000_pch_spt)) {
+       if (hw->mac.type >= e1000_pch_lpt) {
                u32 mac_reg;
 
                mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4);
@@ -1709,8 +1704,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct 
                if (ret_val)
                        return ret_val;
        }
-       if ((hw->mac.type == e1000_pch_lpt) ||
-           (hw->mac.type == e1000_pch_spt)) {
+       if (hw->mac.type >= e1000_pch_lpt) {
                /* Set platform power management values for
                 * Latency Tolerance Reporting (LTR)
                 * Optimized Buffer Flush/Fill (OBFF)
@@ -1723,15 +1717,20 @@ static s32 e1000_check_for_copper_link_ich8lan(struct 
        /* Clear link partner's EEE ability */
        hw->dev_spec.ich8lan.eee_lp_ability = 0;
 
-       /* FEXTNVM6 K1-off workaround */
-       if (hw->mac.type == e1000_pch_spt) {
-               u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG);
+       if (hw->mac.type >= e1000_pch_lpt) {
                u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
 
-               if ((pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE) &&
-                       (hw->dev_spec.ich8lan.disable_k1_off == FALSE))
-                       fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE;
-               else
+               if (hw->mac.type == e1000_pch_spt) {
+                       /* FEXTNVM6 K1-off workaround - for SPT only */
+                       u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG);
+
+                       if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE)
+                               fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE;
+                       else
+                               fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
+               }
+
+               if (hw->dev_spec.ich8lan.disable_k1_off == TRUE)
                        fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
 
                E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6);
@@ -3671,7 +3670,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000
        /* Clear FCERR and DAEL in hw status by writing 1 */
        hsfsts.hsf_status.flcerr = 1;
        hsfsts.hsf_status.dael = 1;
-       if (hw->mac.type == e1000_pch_spt)
+       if (hw->mac.type >= e1000_pch_spt)
                E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
                                      hsfsts.regval & 0xFFFF);
        else
@@ -3691,7 +3690,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000
                 * Begin by setting Flash Cycle Done.
                 */
                hsfsts.hsf_status.flcdone = 1;
-               if (hw->mac.type == e1000_pch_spt)
+               if (hw->mac.type >= e1000_pch_spt)
                        E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
                                              hsfsts.regval & 0xFFFF);
                else
@@ -3718,7 +3717,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000
                         * now set the Flash Cycle Done.
                         */
                        hsfsts.hsf_status.flcdone = 1;
-                       if (hw->mac.type == e1000_pch_spt)
+                       if (hw->mac.type >= e1000_pch_spt)
                                E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
                                                      hsfsts.regval & 0xFFFF);
                        else
@@ -3748,13 +3747,13 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *
        DEBUGFUNC("e1000_flash_cycle_ich8lan");
 
        /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
-       if (hw->mac.type == e1000_pch_spt)
+       if (hw->mac.type >= e1000_pch_spt)
                hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
        else
                hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
        hsflctl.hsf_ctrl.flcgo = 1;
 
-       if (hw->mac.type == e1000_pch_spt)
+       if (hw->mac.type >= e1000_pch_spt)
                E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
                                      hsflctl.regval << 16);
        else
@@ -3837,7 +3836,7 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_
        /* In SPT, only 32 bits access is supported,
         * so this function should not be called.
         */
-       if (hw->mac.type == e1000_pch_spt)
+       if (hw->mac.type >= e1000_pch_spt)
                return -E1000_ERR_NVM;
        else
                ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
@@ -3946,7 +3945,7 @@ static s32 e1000_read_flash_data32_ich8lan(struct e100
        DEBUGFUNC("e1000_read_flash_data_ich8lan");
 
                if (offset > ICH_FLASH_LINEAR_ADDR_MASK ||
-                   hw->mac.type != e1000_pch_spt)
+                   hw->mac.type < e1000_pch_spt)
                        return -E1000_ERR_NVM;
        flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
                             hw->nvm.flash_base_addr);
@@ -4434,7 +4433,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000
 
        DEBUGFUNC("e1000_write_ich8_data");
 
-       if (hw->mac.type == e1000_pch_spt) {
+       if (hw->mac.type >= e1000_pch_spt) {
                if (size != 4 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
                        return -E1000_ERR_NVM;
        } else {
@@ -4454,7 +4453,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000
                /* In SPT, This register is in Lan memory space, not
                 * flash.  Therefore, only 32 bit access is supported
                 */
-               if (hw->mac.type == e1000_pch_spt)
+               if (hw->mac.type >= e1000_pch_spt)
                        hsflctl.regval =
                            E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
                else
@@ -4468,7 +4467,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000
                 * not flash.  Therefore, only 32 bit access is
                 * supported
                 */
-               if (hw->mac.type == e1000_pch_spt)
+               if (hw->mac.type >= e1000_pch_spt)
                        E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
                                              hsflctl.regval << 16);
                else
@@ -4530,7 +4529,7 @@ static s32 e1000_write_flash_data32_ich8lan(struct e10
 
        DEBUGFUNC("e1000_write_flash_data32_ich8lan");
 
-       if (hw->mac.type == e1000_pch_spt) {
+       if (hw->mac.type >= e1000_pch_spt) {
                if (offset > ICH_FLASH_LINEAR_ADDR_MASK)
                        return -E1000_ERR_NVM;
        }
@@ -4546,7 +4545,7 @@ static s32 e1000_write_flash_data32_ich8lan(struct e10
                /* In SPT, This register is in Lan memory space, not
                 * flash.  Therefore, only 32 bit access is supported
                 */
-               if (hw->mac.type == e1000_pch_spt)
+               if (hw->mac.type >= e1000_pch_spt)
                        hsflctl.regval = E1000_READ_FLASH_REG(hw,
                                                              ICH_FLASH_HSFSTS)
                                         >> 16;
@@ -4561,7 +4560,7 @@ static s32 e1000_write_flash_data32_ich8lan(struct e10
                 * not flash.  Therefore, only 32 bit access is
                 * supported
                 */
-               if (hw->mac.type == e1000_pch_spt)
+               if (hw->mac.type >= e1000_pch_spt)
                        E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
                                              hsflctl.regval << 16);
                else
@@ -4763,7 +4762,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000
                        /* Write a value 11 (block Erase) in Flash
                         * Cycle field in hw flash control
                         */
-                       if (hw->mac.type == e1000_pch_spt)
+                       if (hw->mac.type >= e1000_pch_spt)
                                hsflctl.regval =
                                    E1000_READ_FLASH_REG(hw,
                                                         ICH_FLASH_HSFSTS)>>16;
@@ -4773,7 +4772,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000
                                                           ICH_FLASH_HSFCTL);
 
                        hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
-                       if (hw->mac.type == e1000_pch_spt)
+                       if (hw->mac.type >= e1000_pch_spt)
                                E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
                                                      hsflctl.regval << 16);
                        else
@@ -5211,8 +5210,7 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1
        E1000_WRITE_REG(hw, E1000_RFCTL, reg);
 
        /* Enable ECC on Lynxpoint */
-       if ((hw->mac.type == e1000_pch_lpt) ||
-           (hw->mac.type == e1000_pch_spt)) {
+       if (hw->mac.type >= e1000_pch_lpt) {
                reg = E1000_READ_REG(hw, E1000_PBECCSTS);
                reg |= E1000_PBECCSTS_ECC_ENABLE;
                E1000_WRITE_REG(hw, E1000_PBECCSTS, reg);
@@ -5645,7 +5643,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw
                    (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
                    (device_id == E1000_DEV_ID_PCH_I218_LM3) ||
                    (device_id == E1000_DEV_ID_PCH_I218_V3) ||
-                   (hw->mac.type == e1000_pch_spt)) {
+                   (hw->mac.type >= e1000_pch_spt)) {
                        u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
 
                        E1000_WRITE_REG(hw, E1000_FEXTNVM6,

Modified: stable/10/sys/dev/e1000/if_em.c
==============================================================================
--- stable/10/sys/dev/e1000/if_em.c     Thu Aug 31 23:57:34 2017        
(r323079)
+++ stable/10/sys/dev/e1000/if_em.c     Thu Aug 31 23:59:46 2017        
(r323080)
@@ -198,6 +198,12 @@ static em_vendor_info_t em_vendor_info_array[] =
        { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM5,
                                                PCI_ANY_ID, PCI_ANY_ID, 0},
        { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V5, PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM4,
+                                               PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V4, PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_PCH_SPT_I219_LM5,
+                                               PCI_ANY_ID, PCI_ANY_ID, 0},
+       { 0x8086, E1000_DEV_ID_PCH_SPT_I219_V5, PCI_ANY_ID, PCI_ANY_ID, 0},
        /* required last entry */
        { 0, 0, 0, 0, 0}
 };
@@ -5317,6 +5323,8 @@ em_get_wakeup(device_t dev)
        case e1000_ich10lan:
        case e1000_pchlan:
        case e1000_pch2lan:
+       case e1000_pch_lpt:
+       case e1000_pch_spt:
                apme_mask = E1000_WUC_APME;
                adapter->has_amt = TRUE;
                eeprom_data = E1000_READ_REG(&adapter->hw, E1000_WUC);
@@ -5365,32 +5373,13 @@ em_enable_wakeup(device_t dev)
 {
        struct adapter  *adapter = device_get_softc(dev);
        struct ifnet    *ifp = adapter->ifp;
+       int             error = 0;
        u32             pmc, ctrl, ctrl_ext, rctl;
        u16             status;
 
-       if ((pci_find_cap(dev, PCIY_PMG, &pmc) != 0))
+       if (pci_find_cap(dev, PCIY_PMG, &pmc) != 0)
                return;
 
-       /* Advertise the wakeup capability */
-       ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
-       ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3);
-       E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
-       E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN);
-
-       if ((adapter->hw.mac.type == e1000_ich8lan) ||
-           (adapter->hw.mac.type == e1000_pchlan) ||
-           (adapter->hw.mac.type == e1000_ich9lan) ||
-           (adapter->hw.mac.type == e1000_ich10lan))
-               e1000_suspend_workarounds_ich8lan(&adapter->hw);
-
-       /* Keep the laser running on Fiber adapters */
-       if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
-           adapter->hw.phy.media_type == e1000_media_type_internal_serdes) {
-               ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
-               ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA;
-               E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext);
-       }
-
        /*
        ** Determine type of Wakeup: note that wol
        ** is set with all bits on by default.
@@ -5406,11 +5395,37 @@ em_enable_wakeup(device_t dev)
                E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl);
        }
 
-       if ((adapter->hw.mac.type == e1000_pchlan) ||
-           (adapter->hw.mac.type == e1000_pch2lan)) {
-               if (em_enable_phy_wakeup(adapter))
-                       return;
+       if (!(adapter->wol & (E1000_WUFC_EX | E1000_WUFC_MAG | E1000_WUFC_MC)))
+               goto pme;
+
+       /* Advertise the wakeup capability */
+       ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
+       ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3);
+       E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
+
+       /* Keep the laser running on Fiber adapters */
+       if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
+           adapter->hw.phy.media_type == e1000_media_type_internal_serdes) {
+               ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
+               ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA;
+               E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext);
+       }
+
+       if ((adapter->hw.mac.type == e1000_ich8lan) ||
+           (adapter->hw.mac.type == e1000_pchlan) ||
+           (adapter->hw.mac.type == e1000_ich9lan) ||
+           (adapter->hw.mac.type == e1000_ich10lan))
+               e1000_suspend_workarounds_ich8lan(&adapter->hw);
+
+       if ((adapter->hw.mac.type == e1000_pchlan)  ||
+           (adapter->hw.mac.type == e1000_pch2lan) ||
+           (adapter->hw.mac.type == e1000_pch_lpt) ||
+           (adapter->hw.mac.type == e1000_pch_spt)) {
+               error = em_enable_phy_wakeup(adapter);
+               if (error)
+                       goto pme;
        } else {
+               /* Enable wakeup by the MAC */
                E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN);
                E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol);
        }
@@ -5418,10 +5433,10 @@ em_enable_wakeup(device_t dev)
        if (adapter->hw.phy.type == e1000_phy_igp_3)
                e1000_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
 
-        /* Request PME */
+pme:
         status = pci_read_config(dev, pmc + PCIR_POWER_STATUS, 2);
        status &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE);
-       if (ifp->if_capenable & IFCAP_WOL)
+       if (!error && (ifp->if_capenable & IFCAP_WOL))
                status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
         pci_write_config(dev, pmc + PCIR_POWER_STATUS, status, 2);
 

Modified: stable/10/sys/dev/e1000/if_igb.c
==============================================================================
--- stable/10/sys/dev/e1000/if_igb.c    Thu Aug 31 23:57:34 2017        
(r323079)
+++ stable/10/sys/dev/e1000/if_igb.c    Thu Aug 31 23:59:46 2017        
(r323080)
@@ -724,12 +724,6 @@ igb_detach(device_t dev)
        igb_release_manageability(adapter);
        igb_release_hw_control(adapter);
 
-       if (adapter->wol) {
-               E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN);
-               E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol);
-               igb_enable_wakeup(dev);
-       }
-
        /* Unregister VLAN events */
        if (adapter->vlan_attach != NULL)
                EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);
@@ -781,13 +775,8 @@ igb_suspend(device_t dev)
 
         igb_release_manageability(adapter);
        igb_release_hw_control(adapter);
+       igb_enable_wakeup(dev);
 
-        if (adapter->wol) {
-                E1000_WRITE_REG(&adapter->hw, E1000_WUC, E1000_WUC_PME_EN);
-                E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol);
-                igb_enable_wakeup(dev);
-        }
-
        IGB_CORE_UNLOCK(adapter);
 
        return bus_generic_suspend(dev);
@@ -1216,6 +1205,14 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t d
                        ifp->if_capenable ^= IFCAP_LRO;
                        reinit = 1;
                }
+               if (mask & IFCAP_WOL) {
+                       if (mask & IFCAP_WOL_MAGIC)
+                               ifp->if_capenable ^= IFCAP_WOL_MAGIC;
+                       if (mask & IFCAP_WOL_MCAST)
+                               ifp->if_capenable ^= IFCAP_WOL_MCAST;
+                       if (mask & IFCAP_WOL_UCAST)
+                               ifp->if_capenable ^= IFCAP_WOL_UCAST;
+               }
                if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING))
                        igb_init(adapter);
                VLAN_CAPABILITIES(ifp);
@@ -2275,7 +2272,7 @@ igb_stop(void *arg)
        }
 
        e1000_reset_hw(&adapter->hw);
-       E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0);
+       E1000_WRITE_REG(&adapter->hw, E1000_WUFC, 0);
 
        e1000_led_off(&adapter->hw);
        e1000_cleanup_led(&adapter->hw);
@@ -3031,7 +3028,7 @@ igb_reset(struct adapter *adapter)
 
        /* Issue a global reset */
        e1000_reset_hw(hw);
-       E1000_WRITE_REG(hw, E1000_WUC, 0);
+       E1000_WRITE_REG(hw, E1000_WUFC, 0);
 
        /* Reset for AutoMediaDetect */
        if (adapter->flags & IGB_MEDIA_RESET) {
@@ -3122,6 +3119,13 @@ igb_setup_interface(device_t dev, struct adapter *adap
                          |  IFCAP_VLAN_MTU;
 
        /*
+        * Enable only WOL MAGIC by default if WOL is enabled in EEPROM.
+        */
+       ifp->if_capabilities |= IFCAP_WOL;
+       if (adapter->wol)
+               ifp->if_capenable |= IFCAP_WOL_MAGIC;
+
+       /*
        ** Don't turn this on by default, if vlans are
        ** created on another pseudo device (eg. lagg)
        ** then vlan events are not passed thru, breaking
@@ -5311,22 +5315,61 @@ igb_is_valid_ether_addr(uint8_t *addr)
 static void
 igb_enable_wakeup(device_t dev)
 {
-       u16     cap, status;
-       u8      id;
+       struct adapter  *adapter = device_get_softc(dev);
+       struct ifnet    *ifp = adapter->ifp;
+       u32             pmc, ctrl, ctrl_ext, rctl, wuc;
+       u16             status;
 
-       /* First find the capabilities pointer*/
-       cap = pci_read_config(dev, PCIR_CAP_PTR, 2);
-       /* Read the PM Capabilities */
-       id = pci_read_config(dev, cap, 1);
-       if (id != PCIY_PMG)     /* Something wrong */
+       if (pci_find_cap(dev, PCIY_PMG, &pmc) != 0)
                return;
-       /* OK, we have the power capabilities, so
-          now get the status register */
-       cap += PCIR_POWER_STATUS;
-       status = pci_read_config(dev, cap, 2);
-       status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
-       pci_write_config(dev, cap, status, 2);
-       return;
+
+       adapter->wol = E1000_READ_REG(&adapter->hw, E1000_WUFC);
+       if (ifp->if_capenable & IFCAP_WOL_MAGIC)
+               adapter->wol |=  E1000_WUFC_MAG;
+       else
+               adapter->wol &= ~E1000_WUFC_MAG;
+
+       if (ifp->if_capenable & IFCAP_WOL_MCAST) {
+               adapter->wol |=  E1000_WUFC_MC;
+               rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
+               rctl |= E1000_RCTL_MPE;
+               E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl);
+       } else
+               adapter->wol &= ~E1000_WUFC_MC;
+
+       if (ifp->if_capenable & IFCAP_WOL_UCAST)
+               adapter->wol |=  E1000_WUFC_EX;
+       else
+               adapter->wol &= ~E1000_WUFC_EX;
+
+       if (!(adapter->wol & (E1000_WUFC_EX | E1000_WUFC_MAG | E1000_WUFC_MC)))
+               goto pme;
+
+       /* Advertise the wakeup capability */
+       ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
+       ctrl |= (E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN3);
+       E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
+
+       /* Keep the laser running on Fiber adapters */
+       if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
+           adapter->hw.phy.media_type == e1000_media_type_internal_serdes) {
+               ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
+               ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA;
+               E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, ctrl_ext);
+       }
+
+       /* Enable wakeup by the MAC */
+       wuc = E1000_READ_REG(&adapter->hw, E1000_WUC);
+       wuc |= E1000_WUC_PME_EN | E1000_WUC_APME;
+       E1000_WRITE_REG(&adapter->hw, E1000_WUC, wuc);
+       E1000_WRITE_REG(&adapter->hw, E1000_WUFC, adapter->wol);
+
+pme:
+       status = pci_read_config(dev, pmc + PCIR_POWER_STATUS, 2);
+       status &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE);
+       if (ifp->if_capenable & IFCAP_WOL)
+               status |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
+       pci_write_config(dev, pmc + PCIR_POWER_STATUS, status, 2);
 }
 
 static void
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to