[PATCH] e1000: Added functions to save and restore config
authorJesse Brandeburg <jesse.brandeburg@intel.com>
Wed, 18 Jan 2006 21:01:34 +0000 (13:01 -0800)
committerJeff Garzik <jgarzik@pobox.com>
Wed, 18 Jan 2006 21:17:57 +0000 (16:17 -0500)
These functions help restore the driver to active configuration when coming out of resume for power management.

Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: John Ronciak <john.ronciak@intel.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
drivers/net/e1000/e1000_main.c

index 53a9cca06905f6e036c6ce3dc087551ed001c880..501f5108254eef2045ebf39981acf5d0b01c22b2 100644 (file)
@@ -4437,6 +4437,54 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
 }
 
 #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
 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))
                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);
        if(status & E1000_STATUS_LU)
                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");
        }
 
-       pci_save_state(pdev);
-
        if(adapter->hw.mac_type >= e1000_82540 &&
           adapter->hw.media_type == e1000_media_type_copper) {
                manc = E1000_READ_REG(&adapter->hw, MANC);
@@ -4537,6 +4591,7 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state)
        return 0;
 }
 
+#ifdef CONFIG_PM
 static int
 e1000_resume(struct pci_dev *pdev)
 {
@@ -4548,6 +4603,7 @@ e1000_resume(struct pci_dev *pdev)
        retval = pci_set_power_state(pdev, PCI_D0);
        if (retval)
                DPRINTK(PROBE, ERR, "Error in setting power state\n");
+       e1000_pci_restore_state(adapter);
        ret_val = pci_enable_device(pdev);
        pci_set_master(pdev);