ia64/linux-2.6.18-xen.hg

changeset 819:e8a9f8910a3f

Save/restore PCIe/PCI-X states across S3.

This patch is backported from upstream Linux kernel.

commit b56a5a23bfecd9cac9187164a9d5f22d287c48b9
Author: Michael S. Tsirkin <mst@mellanox.co.il>
Date: Mon Aug 21 16:22:22 2006 +0300

PCI: Restore PCI Express capability registers after PM event

Restore PCI Express capability registers after PM event.
This includes maxumum MTU for PCI express and other vital data.

Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>


commit cc692a5f1e9816671b77da77c6d6c463156ba1c7
Author: Stephen Hemminger <shemminger@osdl.org>
Date: Wed Nov 8 16:17:15 2006 -0800

PCI: save/restore PCI-X state

Shouldn't PCI-X state be saved/restored? No device really needs
this
right now. qla24xx (fc HBA) and mthca (infiniband) don't do
suspend,
and sky2 resets its tweaks when links are brought up.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Mar 13 10:08:22 2009 +0000 (2009-03-13)
parents 13a42de2f9c5
children 8b86d11a6eb3
files drivers/pci/pci.c
line diff
     1.1 --- a/drivers/pci/pci.c	Fri Mar 13 08:51:09 2009 +0000
     1.2 +++ b/drivers/pci/pci.c	Fri Mar 13 10:08:22 2009 +0000
     1.3 @@ -428,6 +428,86 @@ pci_power_t pci_choose_state(struct pci_
     1.4  
     1.5  EXPORT_SYMBOL(pci_choose_state);
     1.6  
     1.7 +static int pci_save_pcie_state(struct pci_dev *dev)
     1.8 +{
     1.9 +	int pos, i = 0;
    1.10 +	struct pci_cap_saved_state *save_state;
    1.11 +	u16 *cap;
    1.12 +
    1.13 +	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
    1.14 +	if (pos <= 0)
    1.15 +		return 0;
    1.16 +
    1.17 +	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
    1.18 +	if (!save_state) {
    1.19 +		dev_err(&dev->dev, "buffer not found in %s\n", __FUNCTION__);
    1.20 +		return -ENOMEM;
    1.21 +	}
    1.22 +	cap = (u16 *)&save_state->data[0];
    1.23 +
    1.24 +	pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]);
    1.25 +	pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
    1.26 +	pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
    1.27 +	pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
    1.28 +
    1.29 +	return 0;
    1.30 +}
    1.31 +
    1.32 +static void pci_restore_pcie_state(struct pci_dev *dev)
    1.33 +{
    1.34 +	int i = 0, pos;
    1.35 +	struct pci_cap_saved_state *save_state;
    1.36 +	u16 *cap;
    1.37 +
    1.38 +	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
    1.39 +	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
    1.40 +	if (!save_state || pos <= 0)
    1.41 +		return;
    1.42 +	cap = (u16 *)&save_state->data[0];
    1.43 +
    1.44 +	pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]);
    1.45 +	pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]);
    1.46 +	pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
    1.47 +	pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
    1.48 +}
    1.49 +
    1.50 +
    1.51 +static int pci_save_pcix_state(struct pci_dev *dev)
    1.52 +{
    1.53 +	int pos;
    1.54 +	struct pci_cap_saved_state *save_state;
    1.55 +
    1.56 +	pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
    1.57 +	if (pos <= 0)
    1.58 +		return 0;
    1.59 +
    1.60 +	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
    1.61 +	if (!save_state) {
    1.62 +		dev_err(&dev->dev, "buffer not found in %s\n", __FUNCTION__);
    1.63 +		return -ENOMEM;
    1.64 +	}
    1.65 +
    1.66 +	pci_read_config_word(dev, pos + PCI_X_CMD, (u16 *)save_state->data);
    1.67 +
    1.68 +	return 0;
    1.69 +}
    1.70 +
    1.71 +static void pci_restore_pcix_state(struct pci_dev *dev)
    1.72 +{
    1.73 +	int i = 0, pos;
    1.74 +	struct pci_cap_saved_state *save_state;
    1.75 +	u16 *cap;
    1.76 +
    1.77 +	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
    1.78 +	pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
    1.79 +	if (!save_state || pos <= 0)
    1.80 +		return;
    1.81 +	cap = (u16 *)&save_state->data[0];
    1.82 +
    1.83 +	pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]);
    1.84 +}
    1.85 +
    1.86 +
    1.87  /**
    1.88   * pci_save_state - save the PCI configuration space of a device before suspending
    1.89   * @dev: - PCI device that we're dealing with
    1.90 @@ -443,6 +523,11 @@ pci_save_state(struct pci_dev *dev)
    1.91  		return i;
    1.92  	if ((i = pci_save_msix_state(dev)) != 0)
    1.93  		return i;
    1.94 +	if ((i = pci_save_pcie_state(dev)) != 0)
    1.95 +		return i;
    1.96 +	if ((i = pci_save_pcix_state(dev)) != 0)
    1.97 +		return i;
    1.98 +
    1.99  	return 0;
   1.100  }
   1.101  
   1.102 @@ -456,6 +541,9 @@ pci_restore_state(struct pci_dev *dev)
   1.103  	int i;
   1.104  	int val;
   1.105  
   1.106 +	/* PCI Express register must be restored first */
   1.107 +	pci_restore_pcie_state(dev);
   1.108 +
   1.109  	/*
   1.110  	 * The Base Address register should be programmed before the command
   1.111  	 * register(s)
   1.112 @@ -471,6 +559,7 @@ pci_restore_state(struct pci_dev *dev)
   1.113  				dev->saved_config_space[i]);
   1.114  		}
   1.115  	}
   1.116 +	pci_restore_pcix_state(dev);
   1.117  	pci_restore_msi_state(dev);
   1.118  	pci_restore_msix_state(dev);
   1.119  	return 0;