Merge branch 'topic/core-cleanup' into for-linus
[safe/jmp/linux-2.6] / drivers / net / e1000e / netdev.c
index 2381cb7..dbf8178 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/netdevice.h>
 #include <linux/tcp.h>
 #include <linux/ipv6.h>
+#include <linux/slab.h>
 #include <net/checksum.h>
 #include <net/ip6_checksum.h>
 #include <linux/mii.h>
@@ -450,13 +451,23 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
 
                length = le16_to_cpu(rx_desc->length);
 
-               /* !EOP means multiple descriptors were used to store a single
-                * packet, also make sure the frame isn't just CRC only */
-               if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) {
+               /*
+                * !EOP means multiple descriptors were used to store a single
+                * packet, if that's the case we need to toss it.  In fact, we
+                * need to toss every packet with the EOP bit clear and the
+                * next frame that _does_ have the EOP bit set, as it is by
+                * definition only a frame fragment
+                */
+               if (unlikely(!(status & E1000_RXD_STAT_EOP)))
+                       adapter->flags2 |= FLAG2_IS_DISCARDING;
+
+               if (adapter->flags2 & FLAG2_IS_DISCARDING) {
                        /* All receives must fit into a single buffer */
                        e_dbg("Receive packet consumed multiple buffers\n");
                        /* recycle */
                        buffer_info->skb = skb;
+                       if (status & E1000_RXD_STAT_EOP)
+                               adapter->flags2 &= ~FLAG2_IS_DISCARDING;
                        goto next_desc;
                }
 
@@ -534,10 +545,17 @@ next_desc:
 static void e1000_put_txbuf(struct e1000_adapter *adapter,
                             struct e1000_buffer *buffer_info)
 {
-       buffer_info->dma = 0;
+       if (buffer_info->dma) {
+               if (buffer_info->mapped_as_page)
+                       pci_unmap_page(adapter->pdev, buffer_info->dma,
+                                      buffer_info->length, PCI_DMA_TODEVICE);
+               else
+                       pci_unmap_single(adapter->pdev, buffer_info->dma,
+                                        buffer_info->length,
+                                        PCI_DMA_TODEVICE);
+               buffer_info->dma = 0;
+       }
        if (buffer_info->skb) {
-               skb_dma_unmap(&adapter->pdev->dev, buffer_info->skb,
-                             DMA_TO_DEVICE);
                dev_kfree_skb_any(buffer_info->skb);
                buffer_info->skb = NULL;
        }
@@ -643,6 +661,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
                                i = 0;
                }
 
+               if (i == tx_ring->next_to_use)
+                       break;
                eop = tx_ring->buffer_info[i].next_to_watch;
                eop_desc = E1000_TX_DESC(*tx_ring, eop);
        }
@@ -672,8 +692,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
                adapter->detect_tx_hung = 0;
                if (tx_ring->buffer_info[i].time_stamp &&
                    time_after(jiffies, tx_ring->buffer_info[i].time_stamp
-                              + (adapter->tx_timeout_factor * HZ))
-                   && !(er32(STATUS) & E1000_STATUS_TXOFF)) {
+                              + (adapter->tx_timeout_factor * HZ)) &&
+                   !(er32(STATUS) & E1000_STATUS_TXOFF)) {
                        schedule_work(&adapter->print_hang_task);
                        netif_stop_queue(netdev);
                }
@@ -738,10 +758,16 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
                                 PCI_DMA_FROMDEVICE);
                buffer_info->dma = 0;
 
-               if (!(staterr & E1000_RXD_STAT_EOP)) {
+               /* see !EOP comment in other rx routine */
+               if (!(staterr & E1000_RXD_STAT_EOP))
+                       adapter->flags2 |= FLAG2_IS_DISCARDING;
+
+               if (adapter->flags2 & FLAG2_IS_DISCARDING) {
                        e_dbg("Packet Split buffers didn't pick up the full "
                              "packet\n");
                        dev_kfree_skb_irq(skb);
+                       if (staterr & E1000_RXD_STAT_EOP)
+                               adapter->flags2 &= ~FLAG2_IS_DISCARDING;
                        goto next_desc;
                }
 
@@ -1111,6 +1137,7 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter)
 
        rx_ring->next_to_clean = 0;
        rx_ring->next_to_use = 0;
+       adapter->flags2 &= ~FLAG2_IS_DISCARDING;
 
        writel(0, adapter->hw.hw_addr + rx_ring->head);
        writel(0, adapter->hw.hw_addr + rx_ring->tail);
@@ -2265,8 +2292,6 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
        ew32(TCTL, tctl);
 
        e1000e_config_collision_dist(hw);
-
-       adapter->tx_queue_len = adapter->netdev->tx_queue_len;
 }
 
 /**
@@ -2326,18 +2351,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
        rctl &= ~E1000_RCTL_SZ_4096;
        rctl |= E1000_RCTL_BSEX;
        switch (adapter->rx_buffer_len) {
-       case 256:
-               rctl |= E1000_RCTL_SZ_256;
-               rctl &= ~E1000_RCTL_BSEX;
-               break;
-       case 512:
-               rctl |= E1000_RCTL_SZ_512;
-               rctl &= ~E1000_RCTL_BSEX;
-               break;
-       case 1024:
-               rctl |= E1000_RCTL_SZ_1024;
-               rctl &= ~E1000_RCTL_BSEX;
-               break;
        case 2048:
        default:
                rctl |= E1000_RCTL_SZ_2048;
@@ -2529,22 +2542,14 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
  *  @hw: pointer to the HW structure
  *  @mc_addr_list: array of multicast addresses to program
  *  @mc_addr_count: number of multicast addresses to program
- *  @rar_used_count: the first RAR register free to program
- *  @rar_count: total number of supported Receive Address Registers
  *
- *  Updates the Receive Address Registers and Multicast Table Array.
+ *  Updates the Multicast Table Array.
  *  The caller must have a packed mc_addr_list of multicast addresses.
- *  The parameter rar_count will usually be hw->mac.rar_entry_count
- *  unless there are workarounds that change this.  Currently no func pointer
- *  exists and all implementations are handled in the generic version of this
- *  function.
  **/
 static void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list,
-                                     u32 mc_addr_count, u32 rar_used_count,
-                                     u32 rar_count)
+                                     u32 mc_addr_count)
 {
-       hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count,
-                                       rar_used_count, rar_count);
+       hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, mc_addr_count);
 }
 
 /**
@@ -2560,7 +2565,6 @@ static void e1000_set_multi(struct net_device *netdev)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
-       struct e1000_mac_info *mac = &hw->mac;
        struct dev_mc_list *mc_ptr;
        u8  *mta_list;
        u32 rctl;
@@ -2586,31 +2590,25 @@ static void e1000_set_multi(struct net_device *netdev)
 
        ew32(RCTL, rctl);
 
-       if (netdev->mc_count) {
-               mta_list = kmalloc(netdev->mc_count * 6, GFP_ATOMIC);
+       if (!netdev_mc_empty(netdev)) {
+               mta_list = kmalloc(netdev_mc_count(netdev) * 6, GFP_ATOMIC);
                if (!mta_list)
                        return;
 
                /* prepare a packed array of only addresses. */
-               mc_ptr = netdev->mc_list;
-
-               for (i = 0; i < netdev->mc_count; i++) {
-                       if (!mc_ptr)
-                               break;
-                       memcpy(mta_list + (i*ETH_ALEN), mc_ptr->dmi_addr,
-                              ETH_ALEN);
-                       mc_ptr = mc_ptr->next;
-               }
+               i = 0;
+               netdev_for_each_mc_addr(mc_ptr, netdev)
+                       memcpy(mta_list + (i++ * ETH_ALEN),
+                              mc_ptr->dmi_addr, ETH_ALEN);
 
-               e1000_update_mc_addr_list(hw, mta_list, i, 1,
-                                         mac->rar_entry_count);
+               e1000_update_mc_addr_list(hw, mta_list, i);
                kfree(mta_list);
        } else {
                /*
                 * if we're called from probe, we might not have
                 * anything to do here, so clear out the list
                 */
-               e1000_update_mc_addr_list(hw, NULL, 0, 1, mac->rar_entry_count);
+               e1000_update_mc_addr_list(hw, NULL, 0);
        }
 }
 
@@ -2641,18 +2639,8 @@ static void e1000_configure(struct e1000_adapter *adapter)
  **/
 void e1000e_power_up_phy(struct e1000_adapter *adapter)
 {
-       u16 mii_reg = 0;
-
-       /* Just clear the power down bit to wake the phy back up */
-       if (adapter->hw.phy.media_type == e1000_media_type_copper) {
-               /*
-                * According to the manual, the phy will retain its
-                * settings across a power-down/up cycle
-                */
-               e1e_rphy(&adapter->hw, PHY_CONTROL, &mii_reg);
-               mii_reg &= ~MII_CR_POWER_DOWN;
-               e1e_wphy(&adapter->hw, PHY_CONTROL, mii_reg);
-       }
+       if (adapter->hw.phy.ops.power_up)
+               adapter->hw.phy.ops.power_up(&adapter->hw);
 
        adapter->hw.mac.ops.setup_link(&adapter->hw);
 }
@@ -2660,35 +2648,17 @@ void e1000e_power_up_phy(struct e1000_adapter *adapter)
 /**
  * e1000_power_down_phy - Power down the PHY
  *
- * Power down the PHY so no link is implied when interface is down
- * The PHY cannot be powered down is management or WoL is active
+ * Power down the PHY so no link is implied when interface is down.
+ * The PHY cannot be powered down if management or WoL is active.
  */
 static void e1000_power_down_phy(struct e1000_adapter *adapter)
 {
-       struct e1000_hw *hw = &adapter->hw;
-       u16 mii_reg;
-
        /* WoL is enabled */
        if (adapter->wol)
                return;
 
-       /* non-copper PHY? */
-       if (adapter->hw.phy.media_type != e1000_media_type_copper)
-               return;
-
-       /* reset is blocked because of a SoL/IDER session */
-       if (e1000e_check_mng_mode(hw) || e1000_check_reset_block(hw))
-               return;
-
-       /* manageability (AMT) is enabled */
-       if (er32(MANC) & E1000_MANC_SMBUS_EN)
-               return;
-
-       /* power down the PHY */
-       e1e_rphy(hw, PHY_CONTROL, &mii_reg);
-       mii_reg |= MII_CR_POWER_DOWN;
-       e1e_wphy(hw, PHY_CONTROL, mii_reg);
-       mdelay(1);
+       if (adapter->hw.phy.ops.power_down)
+               adapter->hw.phy.ops.power_down(&adapter->hw);
 }
 
 /**
@@ -2908,7 +2878,6 @@ void e1000e_down(struct e1000_adapter *adapter)
        del_timer_sync(&adapter->watchdog_timer);
        del_timer_sync(&adapter->phy_info_timer);
 
-       netdev->tx_queue_len = adapter->tx_queue_len;
        netif_carrier_off(netdev);
        adapter->link_speed = 0;
        adapter->link_duplex = 0;
@@ -3336,24 +3305,24 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
        if ((hw->phy.type == e1000_phy_82578) ||
            (hw->phy.type == e1000_phy_82577)) {
                e1e_rphy(hw, HV_SCC_UPPER, &phy_data);
-               e1e_rphy(hw, HV_SCC_LOWER, &phy_data);
-               adapter->stats.scc += phy_data;
+               if (!e1e_rphy(hw, HV_SCC_LOWER, &phy_data))
+                       adapter->stats.scc += phy_data;
 
                e1e_rphy(hw, HV_ECOL_UPPER, &phy_data);
-               e1e_rphy(hw, HV_ECOL_LOWER, &phy_data);
-               adapter->stats.ecol += phy_data;
+               if (!e1e_rphy(hw, HV_ECOL_LOWER, &phy_data))
+                       adapter->stats.ecol += phy_data;
 
                e1e_rphy(hw, HV_MCC_UPPER, &phy_data);
-               e1e_rphy(hw, HV_MCC_LOWER, &phy_data);
-               adapter->stats.mcc += phy_data;
+               if (!e1e_rphy(hw, HV_MCC_LOWER, &phy_data))
+                       adapter->stats.mcc += phy_data;
 
                e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data);
-               e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data);
-               adapter->stats.latecol += phy_data;
+               if (!e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data))
+                       adapter->stats.latecol += phy_data;
 
                e1e_rphy(hw, HV_DC_UPPER, &phy_data);
-               e1e_rphy(hw, HV_DC_LOWER, &phy_data);
-               adapter->stats.dc += phy_data;
+               if (!e1e_rphy(hw, HV_DC_LOWER, &phy_data))
+                       adapter->stats.dc += phy_data;
        } else {
                adapter->stats.scc += er32(SCC);
                adapter->stats.ecol += er32(ECOL);
@@ -3381,8 +3350,8 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
        if ((hw->phy.type == e1000_phy_82578) ||
            (hw->phy.type == e1000_phy_82577)) {
                e1e_rphy(hw, HV_COLC_UPPER, &phy_data);
-               e1e_rphy(hw, HV_COLC_LOWER, &phy_data);
-               hw->mac.collision_delta = phy_data;
+               if (!e1e_rphy(hw, HV_COLC_LOWER, &phy_data))
+                       hw->mac.collision_delta = phy_data;
        } else {
                hw->mac.collision_delta = er32(COLC);
        }
@@ -3393,8 +3362,8 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
        if ((hw->phy.type == e1000_phy_82578) ||
            (hw->phy.type == e1000_phy_82577)) {
                e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data);
-               e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data);
-               adapter->stats.tncrs += phy_data;
+               if (!e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data))
+                       adapter->stats.tncrs += phy_data;
        } else {
                if ((hw->mac.type != e1000_82574) &&
                    (hw->mac.type != e1000_82583))
@@ -3498,7 +3467,7 @@ static void e1000_print_link_info(struct e1000_adapter *adapter)
               ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" )));
 }
 
-bool e1000_has_link(struct e1000_adapter *adapter)
+bool e1000e_has_link(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
        bool link_active = 0;
@@ -3579,7 +3548,7 @@ static void e1000_watchdog_task(struct work_struct *work)
        u32 link, tctl;
        int tx_pending = 0;
 
-       link = e1000_has_link(adapter);
+       link = e1000e_has_link(adapter);
        if ((netif_carrier_ok(netdev)) && link) {
                e1000e_enable_receives(adapter);
                goto link_up;
@@ -3619,21 +3588,15 @@ static void e1000_watchdog_task(struct work_struct *work)
                                               "link gets many collisions.\n");
                        }
 
-                       /*
-                        * tweak tx_queue_len according to speed/duplex
-                        * and adjust the timeout factor
-                        */
-                       netdev->tx_queue_len = adapter->tx_queue_len;
+                       /* adjust timeout factor according to speed/duplex */
                        adapter->tx_timeout_factor = 1;
                        switch (adapter->link_speed) {
                        case SPEED_10:
                                txb2b = 0;
-                               netdev->tx_queue_len = 10;
                                adapter->tx_timeout_factor = 16;
                                break;
                        case SPEED_100:
                                txb2b = 0;
-                               netdev->tx_queue_len = 100;
                                adapter->tx_timeout_factor = 10;
                                break;
                        }
@@ -3802,7 +3765,7 @@ static int e1000_tso(struct e1000_adapter *adapter,
                                                         0, IPPROTO_TCP, 0);
                cmd_length = E1000_TXD_CMD_IP;
                ipcse = skb_transport_offset(skb) - 1;
-       } else if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6) {
+       } else if (skb_is_gso_v6(skb)) {
                ipv6_hdr(skb)->payload_len = 0;
                tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
                                                       &ipv6_hdr(skb)->daddr,
@@ -3912,23 +3875,14 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
                        unsigned int mss)
 {
        struct e1000_ring *tx_ring = adapter->tx_ring;
+       struct pci_dev *pdev = adapter->pdev;
        struct e1000_buffer *buffer_info;
        unsigned int len = skb_headlen(skb);
-       unsigned int offset, size, count = 0, i;
+       unsigned int offset = 0, size, count = 0, i;
        unsigned int f;
-       dma_addr_t *map;
 
        i = tx_ring->next_to_use;
 
-       if (skb_dma_map(&adapter->pdev->dev, skb, DMA_TO_DEVICE)) {
-               dev_err(&adapter->pdev->dev, "TX DMA map failed\n");
-               adapter->tx_dma_failed++;
-               return 0;
-       }
-
-       map = skb_shinfo(skb)->dma_maps;
-       offset = 0;
-
        while (len) {
                buffer_info = &tx_ring->buffer_info[i];
                size = min(len, max_per_txd);
@@ -3936,11 +3890,15 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
                buffer_info->length = size;
                buffer_info->time_stamp = jiffies;
                buffer_info->next_to_watch = i;
-               buffer_info->dma = skb_shinfo(skb)->dma_head + offset;
-               count++;
+               buffer_info->dma = pci_map_single(pdev, skb->data + offset,
+                                                 size, PCI_DMA_TODEVICE);
+               buffer_info->mapped_as_page = false;
+               if (pci_dma_mapping_error(pdev, buffer_info->dma))
+                       goto dma_error;
 
                len -= size;
                offset += size;
+               count++;
 
                if (len) {
                        i++;
@@ -3954,7 +3912,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
 
                frag = &skb_shinfo(skb)->frags[f];
                len = frag->size;
-               offset = 0;
+               offset = frag->page_offset;
 
                while (len) {
                        i++;
@@ -3967,7 +3925,12 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
                        buffer_info->length = size;
                        buffer_info->time_stamp = jiffies;
                        buffer_info->next_to_watch = i;
-                       buffer_info->dma = map[f] + offset;
+                       buffer_info->dma = pci_map_page(pdev, frag->page,
+                                                       offset, size,
+                                                       PCI_DMA_TODEVICE);
+                       buffer_info->mapped_as_page = true;
+                       if (pci_dma_mapping_error(pdev, buffer_info->dma))
+                               goto dma_error;
 
                        len -= size;
                        offset += size;
@@ -3979,6 +3942,22 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
        tx_ring->buffer_info[first].next_to_watch = i;
 
        return count;
+
+dma_error:
+       dev_err(&pdev->dev, "TX DMA map failed\n");
+       buffer_info->dma = 0;
+       if (count)
+               count--;
+
+       while (count--) {
+               if (i==0)
+                       i += tx_ring->count;
+               i--;
+               buffer_info = &tx_ring->buffer_info[i];
+               e1000_put_txbuf(adapter, buffer_info);;
+       }
+
+       return 0;
 }
 
 static void e1000_tx_queue(struct e1000_adapter *adapter,
@@ -4051,8 +4030,8 @@ static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter,
        u16 length, offset;
 
        if (vlan_tx_tag_present(skb)) {
-               if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id)
-                   && (adapter->hw.mng_cookie.status &
+               if (!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
+                   (adapter->hw.mng_cookie.status &
                        E1000_MNG_DHCP_COOKIE_STATUS_VLAN)))
                        return 0;
        }
@@ -4304,6 +4283,14 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
                return -EINVAL;
        }
 
+       /* 82573 Errata 17 */
+       if (((adapter->hw.mac.type == e1000_82573) ||
+            (adapter->hw.mac.type == e1000_82574)) &&
+           (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN)) {
+               adapter->flags2 |= FLAG2_DISABLE_ASPM_L1;
+               e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L1);
+       }
+
        while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
                msleep(1);
        /* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */
@@ -4322,13 +4309,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
         * fragmented skbs
         */
 
-       if (max_frame <= 256)
-               adapter->rx_buffer_len = 256;
-       else if (max_frame <= 512)
-               adapter->rx_buffer_len = 512;
-       else if (max_frame <= 1024)
-               adapter->rx_buffer_len = 1024;
-       else if (max_frame <= 2048)
+       if (max_frame <= 2048)
                adapter->rx_buffer_len = 2048;
        else
                adapter->rx_buffer_len = 4096;
@@ -4546,7 +4527,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
                    e1000_media_type_internal_serdes) {
                        /* keep the laser running in D3 */
                        ctrl_ext = er32(CTRL_EXT);
-                       ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA;
+                       ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA;
                        ew32(CTRL_EXT, ctrl_ext);
                }
 
@@ -4632,29 +4613,42 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
        }
 }
 
-static void e1000e_disable_l1aspm(struct pci_dev *pdev)
+#ifdef CONFIG_PCIEASPM
+static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
+{
+       pci_disable_link_state(pdev, state);
+}
+#else
+static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
 {
        int pos;
-       u16 val;
+       u16 reg16;
 
        /*
-        * 82573 workaround - disable L1 ASPM on mobile chipsets
-        *
-        * L1 ASPM on various mobile (ich7) chipsets do not behave properly
-        * resulting in lost data or garbage information on the pci-e link
-        * level. This could result in (false) bad EEPROM checksum errors,
-        * long ping times (up to 2s) or even a system freeze/hang.
-        *
-        * Unfortunately this feature saves about 1W power consumption when
-        * active.
+        * Both device and parent should have the same ASPM setting.
+        * Disable ASPM in downstream component first and then upstream.
         */
-       pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-       pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &val);
-       if (val & 0x2) {
-               dev_warn(&pdev->dev, "Disabling L1 ASPM\n");
-               val &= ~0x2;
-               pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, val);
-       }
+       pos = pci_pcie_cap(pdev);
+       pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+       reg16 &= ~state;
+       pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+
+       if (!pdev->bus->self)
+               return;
+
+       pos = pci_pcie_cap(pdev->bus->self);
+       pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, &reg16);
+       reg16 &= ~state;
+       pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16);
+}
+#endif
+void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
+{
+       dev_info(&pdev->dev, "Disabling ASPM %s %s\n",
+                (state & PCIE_LINK_STATE_L0S) ? "L0s" : "",
+                (state & PCIE_LINK_STATE_L1) ? "L1" : "");
+
+       __e1000e_disable_aspm(pdev, state);
 }
 
 #ifdef CONFIG_PM
@@ -4679,7 +4673,9 @@ static int e1000_resume(struct pci_dev *pdev)
 
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
-       e1000e_disable_l1aspm(pdev);
+       pci_save_state(pdev);
+       if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1)
+               e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);
 
        err = pci_enable_device_mem(pdev);
        if (err) {
@@ -4821,7 +4817,8 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
        int err;
        pci_ers_result_t result;
 
-       e1000e_disable_l1aspm(pdev);
+       if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1)
+               e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);
        err = pci_enable_device_mem(pdev);
        if (err) {
                dev_err(&pdev->dev,
@@ -4830,6 +4827,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
        } else {
                pci_set_master(pdev);
                pci_restore_state(pdev);
+               pci_save_state(pdev);
 
                pci_enable_wake(pdev, PCI_D3hot, 0);
                pci_enable_wake(pdev, PCI_D3cold, 0);
@@ -4914,13 +4912,6 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)
                dev_warn(&adapter->pdev->dev,
                         "Warning: detected DSPD enabled in EEPROM\n");
        }
-
-       ret_val = e1000_read_nvm(hw, NVM_INIT_3GIO_3, 1, &buf);
-       if (!ret_val && (le16_to_cpu(buf) & (3 << 2))) {
-               /* ASPM enable */
-               dev_warn(&adapter->pdev->dev,
-                        "Warning: detected ASPM enabled in EEPROM\n");
-       }
 }
 
 static const struct net_device_ops e1000e_netdev_ops = {
@@ -4969,7 +4960,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        u16 eeprom_data = 0;
        u16 eeprom_apme_mask = E1000_EEPROM_APME;
 
-       e1000e_disable_l1aspm(pdev);
+       if (ei->flags2 & FLAG2_DISABLE_ASPM_L1)
+               e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);
 
        err = pci_enable_device_mem(pdev);
        if (err)
@@ -5138,7 +5130,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
 
        e1000_eeprom_checks(adapter);
 
-       /* copy the MAC address out of the NVM */
+       /* copy the MAC address */
        if (e1000e_read_mac_addr(&adapter->hw))
                e_err("NVM Read Error while reading MAC address\n");
 
@@ -5294,17 +5286,17 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
        cancel_work_sync(&adapter->print_hang_task);
        flush_scheduled_work();
 
+       if (!(netdev->flags & IFF_UP))
+               e1000_power_down_phy(adapter);
+
+       unregister_netdev(netdev);
+
        /*
         * Release control of h/w to f/w.  If f/w is AMT enabled, this
         * would have already happened in close and is redundant.
         */
        e1000_release_hw_control(adapter);
 
-       unregister_netdev(netdev);
-
-       if (!e1000_check_reset_block(&adapter->hw))
-               e1000_phy_hw_reset(&adapter->hw);
-
        e1000e_reset_interrupt_capability(adapter);
        kfree(adapter->tx_ring);
        kfree(adapter->rx_ring);
@@ -5330,7 +5322,7 @@ static struct pci_error_handlers e1000_err_handler = {
        .resume = e1000_io_resume,
 };
 
-static struct pci_device_id e1000_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_COPPER), board_82571 },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_FIBER), board_82571 },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER), board_82571 },
@@ -5370,6 +5362,7 @@ static struct pci_device_id e1000_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_C), board_ich8lan },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M), board_ich8lan },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M_AMT), board_ich8lan },
+       { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_82567V_3), board_ich8lan },
 
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE), board_ich9lan },
        { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_G), board_ich9lan },