aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000e/netdev.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-04-27 15:49:13 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-27 15:49:13 -0400
commite1703b36c358dde24ececba4fd609ecd91433ba3 (patch)
treed59c333d0ad5bf72f165264eba6048c87fdc4e0f /drivers/net/e1000e/netdev.c
parent7ec75c582e639d956ce3afd499f67febe6f902a4 (diff)
parente95ef5d3f6bc60433883e1ef65dac747acd0bf1a (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/netdev.c')
-rw-r--r--drivers/net/e1000e/netdev.c73
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
4637static void e1000e_disable_l1aspm(struct pci_dev *pdev) 4645#ifdef CONFIG_PCIEASPM
4646static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
4647{
4648 pci_disable_link_state(pdev, state);
4649}
4650#else
4651static 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, &reg16);
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, &reg16);
4667 reg16 &= ~state;
4668 pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16);
4669}
4670#endif
4671void 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
4983static const struct net_device_ops e1000e_netdev_ops = { 4999static 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)