diff options
| -rw-r--r-- | drivers/net/e1000e/82571.c | 20 | ||||
| -rw-r--r-- | drivers/net/e1000e/e1000.h | 5 | ||||
| -rw-r--r-- | drivers/net/e1000e/netdev.c | 70 |
3 files changed, 55 insertions, 40 deletions
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 712ccc66ba25..90155552ea09 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c | |||
| @@ -336,7 +336,6 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter) | |||
| 336 | struct e1000_hw *hw = &adapter->hw; | 336 | struct e1000_hw *hw = &adapter->hw; |
| 337 | static int global_quad_port_a; /* global port a indication */ | 337 | static int global_quad_port_a; /* global port a indication */ |
| 338 | struct pci_dev *pdev = adapter->pdev; | 338 | struct pci_dev *pdev = adapter->pdev; |
| 339 | u16 eeprom_data = 0; | ||
| 340 | int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1; | 339 | int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1; |
| 341 | s32 rc; | 340 | s32 rc; |
| 342 | 341 | ||
| @@ -387,16 +386,15 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter) | |||
| 387 | if (pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) | 386 | if (pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) |
| 388 | adapter->flags &= ~FLAG_HAS_WOL; | 387 | adapter->flags &= ~FLAG_HAS_WOL; |
| 389 | break; | 388 | break; |
| 390 | |||
| 391 | case e1000_82573: | 389 | case e1000_82573: |
| 390 | case e1000_82574: | ||
| 391 | case e1000_82583: | ||
| 392 | /* Disable ASPM L0s due to hardware errata */ | ||
| 393 | e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L0S); | ||
| 394 | |||
| 392 | if (pdev->device == E1000_DEV_ID_82573L) { | 395 | if (pdev->device == E1000_DEV_ID_82573L) { |
| 393 | if (e1000_read_nvm(&adapter->hw, NVM_INIT_3GIO_3, 1, | 396 | adapter->flags |= FLAG_HAS_JUMBO_FRAMES; |
| 394 | &eeprom_data) < 0) | 397 | adapter->max_hw_frame_size = DEFAULT_JUMBO; |
| 395 | break; | ||
| 396 | if (!(eeprom_data & NVM_WORD1A_ASPM_MASK)) { | ||
| 397 | adapter->flags |= FLAG_HAS_JUMBO_FRAMES; | ||
| 398 | adapter->max_hw_frame_size = DEFAULT_JUMBO; | ||
| 399 | } | ||
| 400 | } | 398 | } |
| 401 | break; | 399 | break; |
| 402 | default: | 400 | default: |
| @@ -1792,6 +1790,7 @@ struct e1000_info e1000_82571_info = { | |||
| 1792 | | FLAG_RESET_OVERWRITES_LAA /* errata */ | 1790 | | FLAG_RESET_OVERWRITES_LAA /* errata */ |
| 1793 | | FLAG_TARC_SPEED_MODE_BIT /* errata */ | 1791 | | FLAG_TARC_SPEED_MODE_BIT /* errata */ |
| 1794 | | FLAG_APME_CHECK_PORT_B, | 1792 | | FLAG_APME_CHECK_PORT_B, |
| 1793 | .flags2 = FLAG2_DISABLE_ASPM_L1, /* errata 13 */ | ||
| 1795 | .pba = 38, | 1794 | .pba = 38, |
| 1796 | .max_hw_frame_size = DEFAULT_JUMBO, | 1795 | .max_hw_frame_size = DEFAULT_JUMBO, |
| 1797 | .get_variants = e1000_get_variants_82571, | 1796 | .get_variants = e1000_get_variants_82571, |
| @@ -1809,6 +1808,7 @@ struct e1000_info e1000_82572_info = { | |||
| 1809 | | FLAG_RX_CSUM_ENABLED | 1808 | | FLAG_RX_CSUM_ENABLED |
| 1810 | | FLAG_HAS_CTRLEXT_ON_LOAD | 1809 | | FLAG_HAS_CTRLEXT_ON_LOAD |
| 1811 | | FLAG_TARC_SPEED_MODE_BIT, /* errata */ | 1810 | | FLAG_TARC_SPEED_MODE_BIT, /* errata */ |
| 1811 | .flags2 = FLAG2_DISABLE_ASPM_L1, /* errata 13 */ | ||
| 1812 | .pba = 38, | 1812 | .pba = 38, |
| 1813 | .max_hw_frame_size = DEFAULT_JUMBO, | 1813 | .max_hw_frame_size = DEFAULT_JUMBO, |
| 1814 | .get_variants = e1000_get_variants_82571, | 1814 | .get_variants = e1000_get_variants_82571, |
| @@ -1820,13 +1820,11 @@ struct e1000_info e1000_82572_info = { | |||
| 1820 | struct e1000_info e1000_82573_info = { | 1820 | struct e1000_info e1000_82573_info = { |
| 1821 | .mac = e1000_82573, | 1821 | .mac = e1000_82573, |
| 1822 | .flags = FLAG_HAS_HW_VLAN_FILTER | 1822 | .flags = FLAG_HAS_HW_VLAN_FILTER |
| 1823 | | FLAG_HAS_JUMBO_FRAMES | ||
| 1824 | | FLAG_HAS_WOL | 1823 | | FLAG_HAS_WOL |
| 1825 | | FLAG_APME_IN_CTRL3 | 1824 | | FLAG_APME_IN_CTRL3 |
| 1826 | | FLAG_RX_CSUM_ENABLED | 1825 | | FLAG_RX_CSUM_ENABLED |
| 1827 | | FLAG_HAS_SMART_POWER_DOWN | 1826 | | FLAG_HAS_SMART_POWER_DOWN |
| 1828 | | FLAG_HAS_AMT | 1827 | | FLAG_HAS_AMT |
| 1829 | | FLAG_HAS_ERT | ||
| 1830 | | FLAG_HAS_SWSM_ON_LOAD, | 1828 | | FLAG_HAS_SWSM_ON_LOAD, |
| 1831 | .pba = 20, | 1829 | .pba = 20, |
| 1832 | .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, | 1830 | .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, |
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 118bdf483593..ee32b9b27a9f 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
| 38 | #include <linux/netdevice.h> | 38 | #include <linux/netdevice.h> |
| 39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
| 40 | #include <linux/pci-aspm.h> | ||
| 40 | 41 | ||
| 41 | #include "hw.h" | 42 | #include "hw.h" |
| 42 | 43 | ||
| @@ -374,7 +375,7 @@ struct e1000_adapter { | |||
| 374 | struct e1000_info { | 375 | struct e1000_info { |
| 375 | enum e1000_mac_type mac; | 376 | enum e1000_mac_type mac; |
| 376 | unsigned int flags; | 377 | unsigned int flags; |
| 377 | unsigned int flags2; | 378 | unsigned int flags2; |
| 378 | u32 pba; | 379 | u32 pba; |
| 379 | u32 max_hw_frame_size; | 380 | u32 max_hw_frame_size; |
| 380 | s32 (*get_variants)(struct e1000_adapter *); | 381 | s32 (*get_variants)(struct e1000_adapter *); |
| @@ -421,6 +422,7 @@ struct e1000_info { | |||
| 421 | #define FLAG2_CRC_STRIPPING (1 << 0) | 422 | #define FLAG2_CRC_STRIPPING (1 << 0) |
| 422 | #define FLAG2_HAS_PHY_WAKEUP (1 << 1) | 423 | #define FLAG2_HAS_PHY_WAKEUP (1 << 1) |
| 423 | #define FLAG2_IS_DISCARDING (1 << 2) | 424 | #define FLAG2_IS_DISCARDING (1 << 2) |
| 425 | #define FLAG2_DISABLE_ASPM_L1 (1 << 3) | ||
| 424 | 426 | ||
| 425 | #define E1000_RX_DESC_PS(R, i) \ | 427 | #define E1000_RX_DESC_PS(R, i) \ |
| 426 | (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) | 428 | (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) |
| @@ -461,6 +463,7 @@ extern void e1000e_update_stats(struct e1000_adapter *adapter); | |||
| 461 | extern bool e1000e_has_link(struct e1000_adapter *adapter); | 463 | extern bool e1000e_has_link(struct e1000_adapter *adapter); |
| 462 | extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); | 464 | extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); |
| 463 | extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); | 465 | extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); |
| 466 | extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state); | ||
| 464 | 467 | ||
| 465 | extern unsigned int copybreak; | 468 | extern unsigned int copybreak; |
| 466 | 469 | ||
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 73d43c53015a..fb8fc7d1b50d 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
| @@ -4283,6 +4283,14 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) | |||
| 4283 | return -EINVAL; | 4283 | return -EINVAL; |
| 4284 | } | 4284 | } |
| 4285 | 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 | |||
| 4286 | while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) | 4294 | while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) |
| 4287 | msleep(1); | 4295 | msleep(1); |
| 4288 | /* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */ | 4296 | /* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */ |
| @@ -4605,29 +4613,39 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep, | |||
| 4605 | } | 4613 | } |
| 4606 | } | 4614 | } |
| 4607 | 4615 | ||
| 4608 | 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) | ||
| 4609 | { | 4623 | { |
| 4610 | int pos; | 4624 | int pos; |
| 4611 | u16 val; | 4625 | u16 reg16; |
| 4612 | 4626 | ||
| 4613 | /* | 4627 | /* |
| 4614 | * 82573 workaround - disable L1 ASPM on mobile chipsets | 4628 | * Both device and parent should have the same ASPM setting. |
| 4615 | * | 4629 | * Disable ASPM in downstream component first and then upstream. |
| 4616 | * L1 ASPM on various mobile (ich7) chipsets do not behave properly | ||
| 4617 | * resulting in lost data or garbage information on the pci-e link | ||
| 4618 | * level. This could result in (false) bad EEPROM checksum errors, | ||
| 4619 | * long ping times (up to 2s) or even a system freeze/hang. | ||
| 4620 | * | ||
| 4621 | * Unfortunately this feature saves about 1W power consumption when | ||
| 4622 | * active. | ||
| 4623 | */ | 4630 | */ |
| 4624 | pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); | 4631 | pos = pci_pcie_cap(pdev); |
| 4625 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &val); | 4632 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); |
| 4626 | if (val & 0x2) { | 4633 | reg16 &= ~state; |
| 4627 | dev_warn(&pdev->dev, "Disabling L1 ASPM\n"); | 4634 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); |
| 4628 | val &= ~0x2; | 4635 | |
| 4629 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, val); | 4636 | pos = pci_pcie_cap(pdev->bus->self); |
| 4630 | } | 4637 | pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, ®16); |
| 4638 | reg16 &= ~state; | ||
| 4639 | pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16); | ||
| 4640 | } | ||
| 4641 | #endif | ||
| 4642 | void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) | ||
| 4643 | { | ||
| 4644 | dev_info(&pdev->dev, "Disabling ASPM %s %s\n", | ||
| 4645 | (state & PCIE_LINK_STATE_L0S) ? "L0s" : "", | ||
| 4646 | (state & PCIE_LINK_STATE_L1) ? "L1" : ""); | ||
| 4647 | |||
| 4648 | __e1000e_disable_aspm(pdev, state); | ||
| 4631 | } | 4649 | } |
| 4632 | 4650 | ||
| 4633 | #ifdef CONFIG_PM | 4651 | #ifdef CONFIG_PM |
| @@ -4653,7 +4671,8 @@ static int e1000_resume(struct pci_dev *pdev) | |||
| 4653 | pci_set_power_state(pdev, PCI_D0); | 4671 | pci_set_power_state(pdev, PCI_D0); |
| 4654 | pci_restore_state(pdev); | 4672 | pci_restore_state(pdev); |
| 4655 | pci_save_state(pdev); | 4673 | pci_save_state(pdev); |
| 4656 | e1000e_disable_l1aspm(pdev); | 4674 | if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) |
| 4675 | e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1); | ||
| 4657 | 4676 | ||
| 4658 | err = pci_enable_device_mem(pdev); | 4677 | err = pci_enable_device_mem(pdev); |
| 4659 | if (err) { | 4678 | if (err) { |
| @@ -4795,7 +4814,8 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) | |||
| 4795 | int err; | 4814 | int err; |
| 4796 | pci_ers_result_t result; | 4815 | pci_ers_result_t result; |
| 4797 | 4816 | ||
| 4798 | e1000e_disable_l1aspm(pdev); | 4817 | if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) |
| 4818 | e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1); | ||
| 4799 | err = pci_enable_device_mem(pdev); | 4819 | err = pci_enable_device_mem(pdev); |
| 4800 | if (err) { | 4820 | if (err) { |
| 4801 | dev_err(&pdev->dev, | 4821 | dev_err(&pdev->dev, |
| @@ -4889,13 +4909,6 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter) | |||
| 4889 | dev_warn(&adapter->pdev->dev, | 4909 | dev_warn(&adapter->pdev->dev, |
| 4890 | "Warning: detected DSPD enabled in EEPROM\n"); | 4910 | "Warning: detected DSPD enabled in EEPROM\n"); |
| 4891 | } | 4911 | } |
| 4892 | |||
| 4893 | ret_val = e1000_read_nvm(hw, NVM_INIT_3GIO_3, 1, &buf); | ||
| 4894 | if (!ret_val && (le16_to_cpu(buf) & (3 << 2))) { | ||
| 4895 | /* ASPM enable */ | ||
| 4896 | dev_warn(&adapter->pdev->dev, | ||
| 4897 | "Warning: detected ASPM enabled in EEPROM\n"); | ||
| 4898 | } | ||
| 4899 | } | 4912 | } |
| 4900 | 4913 | ||
| 4901 | static const struct net_device_ops e1000e_netdev_ops = { | 4914 | static const struct net_device_ops e1000e_netdev_ops = { |
| @@ -4944,7 +4957,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
| 4944 | u16 eeprom_data = 0; | 4957 | u16 eeprom_data = 0; |
| 4945 | u16 eeprom_apme_mask = E1000_EEPROM_APME; | 4958 | u16 eeprom_apme_mask = E1000_EEPROM_APME; |
| 4946 | 4959 | ||
| 4947 | e1000e_disable_l1aspm(pdev); | 4960 | if (ei->flags2 & FLAG2_DISABLE_ASPM_L1) |
| 4961 | e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1); | ||
| 4948 | 4962 | ||
| 4949 | err = pci_enable_device_mem(pdev); | 4963 | err = pci_enable_device_mem(pdev); |
| 4950 | if (err) | 4964 | if (err) |
