diff options
Diffstat (limited to 'drivers/net/e1000e/netdev.c')
-rw-r--r-- | drivers/net/e1000e/netdev.c | 132 |
1 files changed, 64 insertions, 68 deletions
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 57f149b75fb..dbf81788bb4 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -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> @@ -660,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); } @@ -2289,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; } /** @@ -2541,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); } /** @@ -2572,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; @@ -2598,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); } } @@ -2892,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; @@ -3482,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; @@ -3563,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; @@ -3603,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; } @@ -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 */ @@ -4626,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, ®16); + 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, ®16); + 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 @@ -4674,7 +4674,8 @@ static int e1000_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); pci_save_state(pdev); - 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) { @@ -4816,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, @@ -4910,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 = { @@ -4965,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) @@ -5134,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"); @@ -5326,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 }, |