diff options
author | Jesse Brandeburg <jesse.brandeburg@intel.com> | 2006-01-18 13:01:34 -0800 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2006-01-18 16:17:57 -0500 |
commit | 2f82665fe51b65921e64d5ceb3a6db98f72c4d61 (patch) | |
tree | 2b179bb39363508ca188a0ade30e98e36a0bf601 | |
parent | b92ff8ee5763ee0b408f3cf2360f58dd7ea9c5da (diff) | |
download | op-kernel-dev-2f82665fe51b65921e64d5ceb3a6db98f72c4d61.zip op-kernel-dev-2f82665fe51b65921e64d5ceb3a6db98f72c4d61.tar.gz |
[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>
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 60 |
1 files changed, 58 insertions, 2 deletions
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 @@ 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); |