|
@@ -4437,6 +4437,54 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_PM
|
|
#ifdef CONFIG_PM
|
|
|
|
+/* these functions save and restore 16 or 64 dwords (64-256 bytes) of config
|
|
|
|
+ * space versus the 64 bytes that pci_[save|restore]_state handle
|
|
|
|
+ */
|
|
|
|
+#define PCIE_CONFIG_SPACE_LEN 256
|
|
|
|
+#define PCI_CONFIG_SPACE_LEN 64
|
|
|
|
+static int
|
|
|
|
+e1000_pci_save_state(struct e1000_adapter *adapter)
|
|
|
|
+{
|
|
|
|
+ struct pci_dev *dev = adapter->pdev;
|
|
|
|
+ int size;
|
|
|
|
+ int i;
|
|
|
|
+ if (adapter->hw.mac_type >= e1000_82571)
|
|
|
|
+ size = PCIE_CONFIG_SPACE_LEN;
|
|
|
|
+ else
|
|
|
|
+ size = PCI_CONFIG_SPACE_LEN;
|
|
|
|
+
|
|
|
|
+ WARN_ON(adapter->config_space != NULL);
|
|
|
|
+
|
|
|
|
+ adapter->config_space = kmalloc(size, GFP_KERNEL);
|
|
|
|
+ if (!adapter->config_space) {
|
|
|
|
+ DPRINTK(PROBE, ERR, "unable to allocate %d bytes\n", size);
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ }
|
|
|
|
+ for (i = 0; i < (size / 4); i++)
|
|
|
|
+ pci_read_config_dword(dev, i * 4, &adapter->config_space[i]);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+e1000_pci_restore_state(struct e1000_adapter *adapter)
|
|
|
|
+{
|
|
|
|
+ struct pci_dev *dev = adapter->pdev;
|
|
|
|
+ int size;
|
|
|
|
+ int i;
|
|
|
|
+ if (adapter->config_space == NULL)
|
|
|
|
+ return;
|
|
|
|
+ if (adapter->hw.mac_type >= e1000_82571)
|
|
|
|
+ size = PCIE_CONFIG_SPACE_LEN;
|
|
|
|
+ else
|
|
|
|
+ size = PCI_CONFIG_SPACE_LEN;
|
|
|
|
+ for (i = 0; i < (size / 4); i++)
|
|
|
|
+ pci_write_config_dword(dev, i * 4, adapter->config_space[i]);
|
|
|
|
+ kfree(adapter->config_space);
|
|
|
|
+ adapter->config_space = NULL;
|
|
|
|
+ return;
|
|
|
|
+}
|
|
|
|
+#endif /* CONFIG_PM */
|
|
|
|
+
|
|
static int
|
|
static int
|
|
e1000_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
e1000_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
{
|
|
{
|
|
@@ -4451,6 +4499,14 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
if(netif_running(netdev))
|
|
if(netif_running(netdev))
|
|
e1000_down(adapter);
|
|
e1000_down(adapter);
|
|
|
|
|
|
|
|
+#ifdef CONFIG_PM
|
|
|
|
+ /* implement our own version of pci_save_state(pdev) because pci
|
|
|
|
+ * express adapters have larger 256 byte config spaces */
|
|
|
|
+ retval = e1000_pci_save_state(adapter);
|
|
|
|
+ if (retval)
|
|
|
|
+ return retval;
|
|
|
|
+#endif
|
|
|
|
+
|
|
status = E1000_READ_REG(&adapter->hw, STATUS);
|
|
status = E1000_READ_REG(&adapter->hw, STATUS);
|
|
if(status & E1000_STATUS_LU)
|
|
if(status & E1000_STATUS_LU)
|
|
wufc &= ~E1000_WUFC_LNKC;
|
|
wufc &= ~E1000_WUFC_LNKC;
|
|
@@ -4507,8 +4563,6 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
|
|
DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
|
|
}
|
|
}
|
|
|
|
|
|
- pci_save_state(pdev);
|
|
|
|
-
|
|
|
|
if(adapter->hw.mac_type >= e1000_82540 &&
|
|
if(adapter->hw.mac_type >= e1000_82540 &&
|
|
adapter->hw.media_type == e1000_media_type_copper) {
|
|
adapter->hw.media_type == e1000_media_type_copper) {
|
|
manc = E1000_READ_REG(&adapter->hw, MANC);
|
|
manc = E1000_READ_REG(&adapter->hw, MANC);
|
|
@@ -4537,6 +4591,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef CONFIG_PM
|
|
static int
|
|
static int
|
|
e1000_resume(struct pci_dev *pdev)
|
|
e1000_resume(struct pci_dev *pdev)
|
|
{
|
|
{
|
|
@@ -4548,6 +4603,7 @@ e1000_resume(struct pci_dev *pdev)
|
|
retval = pci_set_power_state(pdev, PCI_D0);
|
|
retval = pci_set_power_state(pdev, PCI_D0);
|
|
if (retval)
|
|
if (retval)
|
|
DPRINTK(PROBE, ERR, "Error in setting power state\n");
|
|
DPRINTK(PROBE, ERR, "Error in setting power state\n");
|
|
|
|
+ e1000_pci_restore_state(adapter);
|
|
ret_val = pci_enable_device(pdev);
|
|
ret_val = pci_enable_device(pdev);
|
|
pci_set_master(pdev);
|
|
pci_set_master(pdev);
|
|
|
|
|