|
@@ -4283,6 +4283,14 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ /* 82573 Errata 17 */
|
|
|
+ if (((adapter->hw.mac.type == e1000_82573) ||
|
|
|
+ (adapter->hw.mac.type == e1000_82574)) &&
|
|
|
+ (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN)) {
|
|
|
+ adapter->flags2 |= FLAG2_DISABLE_ASPM_L1;
|
|
|
+ e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L1);
|
|
|
+ }
|
|
|
+
|
|
|
while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
|
|
|
msleep(1);
|
|
|
/* 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,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void e1000e_disable_l1aspm(struct pci_dev *pdev)
|
|
|
+#ifdef CONFIG_PCIEASPM
|
|
|
+static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
|
|
|
+{
|
|
|
+ pci_disable_link_state(pdev, state);
|
|
|
+}
|
|
|
+#else
|
|
|
+static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
|
|
|
{
|
|
|
int pos;
|
|
|
- u16 val;
|
|
|
+ u16 reg16;
|
|
|
|
|
|
/*
|
|
|
- * 82573 workaround - disable L1 ASPM on mobile chipsets
|
|
|
- *
|
|
|
- * L1 ASPM on various mobile (ich7) chipsets do not behave properly
|
|
|
- * resulting in lost data or garbage information on the pci-e link
|
|
|
- * level. This could result in (false) bad EEPROM checksum errors,
|
|
|
- * long ping times (up to 2s) or even a system freeze/hang.
|
|
|
- *
|
|
|
- * Unfortunately this feature saves about 1W power consumption when
|
|
|
- * active.
|
|
|
+ * Both device and parent should have the same ASPM setting.
|
|
|
+ * Disable ASPM in downstream component first and then upstream.
|
|
|
*/
|
|
|
- pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
|
|
|
- pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &val);
|
|
|
- if (val & 0x2) {
|
|
|
- dev_warn(&pdev->dev, "Disabling L1 ASPM\n");
|
|
|
- val &= ~0x2;
|
|
|
- pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, val);
|
|
|
- }
|
|
|
+ pos = pci_pcie_cap(pdev);
|
|
|
+ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16);
|
|
|
+ reg16 &= ~state;
|
|
|
+ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
|
|
|
+
|
|
|
+ pos = pci_pcie_cap(pdev->bus->self);
|
|
|
+ pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, ®16);
|
|
|
+ reg16 &= ~state;
|
|
|
+ pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16);
|
|
|
+}
|
|
|
+#endif
|
|
|
+void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
|
|
|
+{
|
|
|
+ dev_info(&pdev->dev, "Disabling ASPM %s %s\n",
|
|
|
+ (state & PCIE_LINK_STATE_L0S) ? "L0s" : "",
|
|
|
+ (state & PCIE_LINK_STATE_L1) ? "L1" : "");
|
|
|
+
|
|
|
+ __e1000e_disable_aspm(pdev, state);
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_PM
|
|
@@ -4653,7 +4671,8 @@ static int e1000_resume(struct pci_dev *pdev)
|
|
|
pci_set_power_state(pdev, PCI_D0);
|
|
|
pci_restore_state(pdev);
|
|
|
pci_save_state(pdev);
|
|
|
- e1000e_disable_l1aspm(pdev);
|
|
|
+ if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1)
|
|
|
+ e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);
|
|
|
|
|
|
err = pci_enable_device_mem(pdev);
|
|
|
if (err) {
|
|
@@ -4795,7 +4814,8 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
|
|
|
int err;
|
|
|
pci_ers_result_t result;
|
|
|
|
|
|
- e1000e_disable_l1aspm(pdev);
|
|
|
+ if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1)
|
|
|
+ e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);
|
|
|
err = pci_enable_device_mem(pdev);
|
|
|
if (err) {
|
|
|
dev_err(&pdev->dev,
|
|
@@ -4889,13 +4909,6 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)
|
|
|
dev_warn(&adapter->pdev->dev,
|
|
|
"Warning: detected DSPD enabled in EEPROM\n");
|
|
|
}
|
|
|
-
|
|
|
- ret_val = e1000_read_nvm(hw, NVM_INIT_3GIO_3, 1, &buf);
|
|
|
- if (!ret_val && (le16_to_cpu(buf) & (3 << 2))) {
|
|
|
- /* ASPM enable */
|
|
|
- dev_warn(&adapter->pdev->dev,
|
|
|
- "Warning: detected ASPM enabled in EEPROM\n");
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
static const struct net_device_ops e1000e_netdev_ops = {
|
|
@@ -4944,7 +4957,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
|
|
u16 eeprom_data = 0;
|
|
|
u16 eeprom_apme_mask = E1000_EEPROM_APME;
|
|
|
|
|
|
- e1000e_disable_l1aspm(pdev);
|
|
|
+ if (ei->flags2 & FLAG2_DISABLE_ASPM_L1)
|
|
|
+ e1000e_disable_aspm(pdev, PCIE_LINK_STATE_L1);
|
|
|
|
|
|
err = pci_enable_device_mem(pdev);
|
|
|
if (err)
|