diff options
Diffstat (limited to 'drivers/net/e1000e/netdev.c')
-rw-r--r-- | drivers/net/e1000e/netdev.c | 75 |
1 files changed, 47 insertions, 28 deletions
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index cfd09cea7214..dbf81788bb40 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -661,6 +661,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) | |||
661 | i = 0; | 661 | i = 0; |
662 | } | 662 | } |
663 | 663 | ||
664 | if (i == tx_ring->next_to_use) | ||
665 | break; | ||
664 | eop = tx_ring->buffer_info[i].next_to_watch; | 666 | eop = tx_ring->buffer_info[i].next_to_watch; |
665 | eop_desc = E1000_TX_DESC(*tx_ring, eop); | 667 | eop_desc = E1000_TX_DESC(*tx_ring, eop); |
666 | } | 668 | } |
@@ -4281,6 +4283,14 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) | |||
4281 | return -EINVAL; | 4283 | return -EINVAL; |
4282 | } | 4284 | } |
4283 | 4285 | ||
4286 | /* 82573 Errata 17 */ | ||
4287 | if (((adapter->hw.mac.type == e1000_82573) || | ||
4288 | (adapter->hw.mac.type == e1000_82574)) && | ||
4289 | (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN)) { | ||
4290 | adapter->flags2 |= FLAG2_DISABLE_ASPM_L1; | ||
4291 | e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L1); | ||
4292 | } | ||
4293 | |||
4284 | while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) | 4294 | while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) |
4285 | msleep(1); | 4295 | msleep(1); |
4286 | /* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */ | 4296 | /* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */ |
@@ -4603,29 +4613,42 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep, | |||
4603 | } | 4613 | } |
4604 | } | 4614 | } |
4605 | 4615 | ||
4606 | static void e1000e_disable_l1aspm(struct pci_dev *pdev) | 4616 | #ifdef CONFIG_PCIEASPM |
4617 | static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) | ||
4618 | { | ||
4619 | pci_disable_link_state(pdev, state); | ||
4620 | } | ||
4621 | #else | ||
4622 | static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) | ||
4607 | { | 4623 | { |
4608 | int pos; | 4624 | int pos; |
4609 | u16 val; | 4625 | u16 reg16; |
4610 | 4626 | ||
4611 | /* | 4627 | /* |
4612 | * 82573 workaround - disable L1 ASPM on mobile chipsets | 4628 | * Both device and parent should have the same ASPM setting. |
4613 | * | 4629 | * Disable ASPM in downstream component first and then upstream. |
4614 | * L1 ASPM on various mobile (ich7) chipsets do not behave properly | ||
4615 | * resulting in lost data or garbage information on the pci-e link | ||
4616 | * level. This could result in (false) bad EEPROM checksum errors, | ||
4617 | * long ping times (up to 2s) or even a system freeze/hang. | ||
4618 | * | ||
4619 | * Unfortunately this feature saves about 1W power consumption when | ||
4620 | * active. | ||
4621 | */ | 4630 | */ |
4622 | pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); | 4631 | pos = pci_pcie_cap(pdev); |
4623 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &val); | 4632 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); |
4624 | if (val & 0x2) { | 4633 | reg16 &= ~state; |
4625 | dev_warn(&pdev->dev, "Disabling L1 ASPM\n"); | 4634 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); |
4626 | val &= ~0x2; | 4635 | |
4627 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, val); | 4636 | if (!pdev->bus->self) |
4628 | } | 4637 | return; |
4638 | |||
4639 | pos = pci_pcie_cap(pdev->bus->self); | ||
4640 | pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, ®16); | ||
4641 | reg16 &= ~state; | ||
4642 | pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16); | ||
4643 | } | ||
4644 | #endif | ||
4645 | void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) | ||
4646 | { | ||
4647 | dev_info(&pdev->dev, "Disabling ASPM %s %s\n", | ||
4648 | (state & PCIE_LINK_STATE_L0S) ? "L0s" : "", | ||
4649 | (state & PCIE_LINK_STATE_L1) ? "L1" : ""); | ||
4650 | |||
4651 | __e1000e_disable_aspm(pdev, state); | ||
4629 | } | 4652 | } |
4630 | 4653 | ||
4631 | #ifdef CONFIG_PM | 4654 | #ifdef CONFIG_PM |
@@ -4651,7 +4674,8 @@ static int e1000_resume(struct pci_dev *pdev) | |||
4651 | pci_set_power_state(pdev, PCI_D0); | 4674 | pci_set_power_state(pdev, PCI_D0); |
4652 | pci_restore_state(pdev); | 4675 | pci_restore_state(pdev); |
4653 | pci_save_state(pdev); | 4676 | pci_save_state(pdev); |
4654 | e1000e_disable_l1aspm(pdev); | 4677 | if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) |
4678 | e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1); | ||
4655 | 4679 | ||
4656 | err = pci_enable_device_mem(pdev); | 4680 | err = pci_enable_device_mem(pdev); |
4657 | if (err) { | 4681 | if (err) { |
@@ -4793,7 +4817,8 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) | |||
4793 | int err; | 4817 | int err; |
4794 | pci_ers_result_t result; | 4818 | pci_ers_result_t result; |
4795 | 4819 | ||
4796 | e1000e_disable_l1aspm(pdev); | 4820 | if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) |
4821 | e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1); | ||
4797 | err = pci_enable_device_mem(pdev); | 4822 | err = pci_enable_device_mem(pdev); |
4798 | if (err) { | 4823 | if (err) { |
4799 | dev_err(&pdev->dev, | 4824 | dev_err(&pdev->dev, |
@@ -4887,13 +4912,6 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter) | |||
4887 | dev_warn(&adapter->pdev->dev, | 4912 | dev_warn(&adapter->pdev->dev, |
4888 | "Warning: detected DSPD enabled in EEPROM\n"); | 4913 | "Warning: detected DSPD enabled in EEPROM\n"); |
4889 | } | 4914 | } |
4890 | |||
4891 | ret_val = e1000_read_nvm(hw, NVM_INIT_3GIO_3, 1, &buf); | ||
4892 | if (!ret_val && (le16_to_cpu(buf) & (3 << 2))) { | ||
4893 | /* ASPM enable */ | ||
4894 | dev_warn(&adapter->pdev->dev, | ||
4895 | "Warning: detected ASPM enabled in EEPROM\n"); | ||
4896 | } | ||
4897 | } | 4915 | } |
4898 | 4916 | ||
4899 | static const struct net_device_ops e1000e_netdev_ops = { | 4917 | static const struct net_device_ops e1000e_netdev_ops = { |
@@ -4942,7 +4960,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
4942 | u16 eeprom_data = 0; | 4960 | u16 eeprom_data = 0; |
4943 | u16 eeprom_apme_mask = E1000_EEPROM_APME; | 4961 | u16 eeprom_apme_mask = E1000_EEPROM_APME; |
4944 | 4962 | ||
4945 | e1000e_disable_l1aspm(pdev); | 4963 | if (ei->flags2 & FLAG2_DISABLE_ASPM_L1) |
4964 | e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1); | ||
4946 | 4965 | ||
4947 | err = pci_enable_device_mem(pdev); | 4966 | err = pci_enable_device_mem(pdev); |
4948 | if (err) | 4967 | if (err) |