diff options
Diffstat (limited to 'drivers/net/e1000e/netdev.c')
-rw-r--r-- | drivers/net/e1000e/netdev.c | 73 |
1 files changed, 45 insertions, 28 deletions
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 5f70c437fa41..2476f8c24c54 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -4310,6 +4310,14 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) | |||
4310 | return -EINVAL; | 4310 | return -EINVAL; |
4311 | } | 4311 | } |
4312 | 4312 | ||
4313 | /* 82573 Errata 17 */ | ||
4314 | if (((adapter->hw.mac.type == e1000_82573) || | ||
4315 | (adapter->hw.mac.type == e1000_82574)) && | ||
4316 | (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN)) { | ||
4317 | adapter->flags2 |= FLAG2_DISABLE_ASPM_L1; | ||
4318 | e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L1); | ||
4319 | } | ||
4320 | |||
4313 | while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) | 4321 | while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) |
4314 | msleep(1); | 4322 | msleep(1); |
4315 | /* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */ | 4323 | /* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */ |
@@ -4634,29 +4642,39 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep, | |||
4634 | } | 4642 | } |
4635 | } | 4643 | } |
4636 | 4644 | ||
4637 | static void e1000e_disable_l1aspm(struct pci_dev *pdev) | 4645 | #ifdef CONFIG_PCIEASPM |
4646 | static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) | ||
4647 | { | ||
4648 | pci_disable_link_state(pdev, state); | ||
4649 | } | ||
4650 | #else | ||
4651 | static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) | ||
4638 | { | 4652 | { |
4639 | int pos; | 4653 | int pos; |
4640 | u16 val; | 4654 | u16 reg16; |
4641 | 4655 | ||
4642 | /* | 4656 | /* |
4643 | * 82573 workaround - disable L1 ASPM on mobile chipsets | 4657 | * Both device and parent should have the same ASPM setting. |
4644 | * | 4658 | * Disable ASPM in downstream component first and then upstream. |
4645 | * L1 ASPM on various mobile (ich7) chipsets do not behave properly | ||
4646 | * resulting in lost data or garbage information on the pci-e link | ||
4647 | * level. This could result in (false) bad EEPROM checksum errors, | ||
4648 | * long ping times (up to 2s) or even a system freeze/hang. | ||
4649 | * | ||
4650 | * Unfortunately this feature saves about 1W power consumption when | ||
4651 | * active. | ||
4652 | */ | 4659 | */ |
4653 | pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); | 4660 | pos = pci_pcie_cap(pdev); |
4654 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &val); | 4661 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); |
4655 | if (val & 0x2) { | 4662 | reg16 &= ~state; |
4656 | dev_warn(&pdev->dev, "Disabling L1 ASPM\n"); | 4663 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); |
4657 | val &= ~0x2; | 4664 | |
4658 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, val); | 4665 | pos = pci_pcie_cap(pdev->bus->self); |
4659 | } | 4666 | pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, ®16); |
4667 | reg16 &= ~state; | ||
4668 | pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16); | ||
4669 | } | ||
4670 | #endif | ||
4671 | void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) | ||
4672 | { | ||
4673 | dev_info(&pdev->dev, "Disabling ASPM %s %s\n", | ||
4674 | (state & PCIE_LINK_STATE_L0S) ? "L0s" : "", | ||
4675 | (state & PCIE_LINK_STATE_L1) ? "L1" : ""); | ||
4676 | |||
4677 | __e1000e_disable_aspm(pdev, state); | ||
4660 | } | 4678 | } |
4661 | 4679 | ||
4662 | #ifdef CONFIG_PM_OPS | 4680 | #ifdef CONFIG_PM_OPS |
@@ -4672,7 +4690,11 @@ static int __e1000_resume(struct pci_dev *pdev) | |||
4672 | struct e1000_hw *hw = &adapter->hw; | 4690 | struct e1000_hw *hw = &adapter->hw; |
4673 | u32 err; | 4691 | u32 err; |
4674 | 4692 | ||
4675 | e1000e_disable_l1aspm(pdev); | 4693 | pci_set_power_state(pdev, PCI_D0); |
4694 | pci_restore_state(pdev); | ||
4695 | pci_save_state(pdev); | ||
4696 | if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) | ||
4697 | e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1); | ||
4676 | 4698 | ||
4677 | e1000e_set_interrupt_capability(adapter); | 4699 | e1000e_set_interrupt_capability(adapter); |
4678 | if (netif_running(netdev)) { | 4700 | if (netif_running(netdev)) { |
@@ -4877,7 +4899,8 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) | |||
4877 | int err; | 4899 | int err; |
4878 | pci_ers_result_t result; | 4900 | pci_ers_result_t result; |
4879 | 4901 | ||
4880 | e1000e_disable_l1aspm(pdev); | 4902 | if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) |
4903 | e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1); | ||
4881 | err = pci_enable_device_mem(pdev); | 4904 | err = pci_enable_device_mem(pdev); |
4882 | if (err) { | 4905 | if (err) { |
4883 | dev_err(&pdev->dev, | 4906 | dev_err(&pdev->dev, |
@@ -4971,13 +4994,6 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter) | |||
4971 | dev_warn(&adapter->pdev->dev, | 4994 | dev_warn(&adapter->pdev->dev, |
4972 | "Warning: detected DSPD enabled in EEPROM\n"); | 4995 | "Warning: detected DSPD enabled in EEPROM\n"); |
4973 | } | 4996 | } |
4974 | |||
4975 | ret_val = e1000_read_nvm(hw, NVM_INIT_3GIO_3, 1, &buf); | ||
4976 | if (!ret_val && (le16_to_cpu(buf) & (3 << 2))) { | ||
4977 | /* ASPM enable */ | ||
4978 | dev_warn(&adapter->pdev->dev, | ||
4979 | "Warning: detected ASPM enabled in EEPROM\n"); | ||
4980 | } | ||
4981 | } | 4997 | } |
4982 | 4998 | ||
4983 | static const struct net_device_ops e1000e_netdev_ops = { | 4999 | static const struct net_device_ops e1000e_netdev_ops = { |
@@ -5026,7 +5042,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
5026 | u16 eeprom_data = 0; | 5042 | u16 eeprom_data = 0; |
5027 | u16 eeprom_apme_mask = E1000_EEPROM_APME; | 5043 | u16 eeprom_apme_mask = E1000_EEPROM_APME; |
5028 | 5044 | ||
5029 | e1000e_disable_l1aspm(pdev); | 5045 | if (ei->flags2 & FLAG2_DISABLE_ASPM_L1) |
5046 | e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1); | ||
5030 | 5047 | ||
5031 | err = pci_enable_device_mem(pdev); | 5048 | err = pci_enable_device_mem(pdev); |
5032 | if (err) | 5049 | if (err) |