[PATCH] e1000: Added functions to save and restore config

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>
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 53a9cca..501f510 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -4437,6 +4437,54 @@
 }
 
 #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 @@
 	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 @@
 			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 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
 static int
 e1000_resume(struct pci_dev *pdev)
 {
@@ -4548,6 +4603,7 @@
 	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);