diff options
author | David S. Miller <davem@davemloft.net> | 2010-04-27 15:49:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-27 15:49:13 -0400 |
commit | e1703b36c358dde24ececba4fd609ecd91433ba3 (patch) | |
tree | d59c333d0ad5bf72f165264eba6048c87fdc4e0f /drivers/net/e1000e | |
parent | 7ec75c582e639d956ce3afd499f67febe6f902a4 (diff) | |
parent | e95ef5d3f6bc60433883e1ef65dac747acd0bf1a (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/e100.c
drivers/net/e1000e/netdev.c
Diffstat (limited to 'drivers/net/e1000e')
-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 | 73 |
3 files changed, 58 insertions, 40 deletions
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 4b0016d69530..17a25e19bbba 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 12648a1cdb78..906c4daaabe9 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 | ||
@@ -370,7 +371,7 @@ struct e1000_adapter { | |||
370 | struct e1000_info { | 371 | struct e1000_info { |
371 | enum e1000_mac_type mac; | 372 | enum e1000_mac_type mac; |
372 | unsigned int flags; | 373 | unsigned int flags; |
373 | unsigned int flags2; | 374 | unsigned int flags2; |
374 | u32 pba; | 375 | u32 pba; |
375 | u32 max_hw_frame_size; | 376 | u32 max_hw_frame_size; |
376 | s32 (*get_variants)(struct e1000_adapter *); | 377 | s32 (*get_variants)(struct e1000_adapter *); |
@@ -417,6 +418,7 @@ struct e1000_info { | |||
417 | #define FLAG2_CRC_STRIPPING (1 << 0) | 418 | #define FLAG2_CRC_STRIPPING (1 << 0) |
418 | #define FLAG2_HAS_PHY_WAKEUP (1 << 1) | 419 | #define FLAG2_HAS_PHY_WAKEUP (1 << 1) |
419 | #define FLAG2_IS_DISCARDING (1 << 2) | 420 | #define FLAG2_IS_DISCARDING (1 << 2) |
421 | #define FLAG2_DISABLE_ASPM_L1 (1 << 3) | ||
420 | 422 | ||
421 | #define E1000_RX_DESC_PS(R, i) \ | 423 | #define E1000_RX_DESC_PS(R, i) \ |
422 | (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) | 424 | (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) |
@@ -457,6 +459,7 @@ extern void e1000e_update_stats(struct e1000_adapter *adapter); | |||
457 | extern bool e1000e_has_link(struct e1000_adapter *adapter); | 459 | extern bool e1000e_has_link(struct e1000_adapter *adapter); |
458 | extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); | 460 | extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); |
459 | extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); | 461 | extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); |
462 | extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state); | ||
460 | 463 | ||
461 | extern unsigned int copybreak; | 464 | extern unsigned int copybreak; |
462 | 465 | ||
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) |