# HG changeset patch # User Yu Zhao # Date 1237268742 14400 # Node ID 2629935bf356bb7118f8691a46e90daed77c3b48 # Parent 92730fa710446b2502809faa72bb29fda95ba878 PCI: restore saved SR-IOV state Restore the volatile registers in the SR-IOV capability after the D3->D0 transition. Signed-off-by: Yu Zhao diff -r 92730fa71044 -r 2629935bf356 drivers/pci/iov.c --- a/drivers/pci/iov.c Tue Mar 17 01:43:05 2009 -0400 +++ b/drivers/pci/iov.c Tue Mar 17 01:45:42 2009 -0400 @@ -125,6 +125,25 @@ dev->sriov = NULL; } +static void sriov_restore_state(struct pci_dev *dev) +{ + int i; + u16 ctrl; + struct pci_sriov *iov = dev->sriov; + + pci_read_config_word(dev, iov->pos + PCI_SRIOV_CTRL, &ctrl); + if (ctrl & PCI_SRIOV_CTRL_VFE) + return; + + for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++) + pci_update_resource(dev, i); + + pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz); + pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); + if (iov->ctrl & PCI_SRIOV_CTRL_VFE) + msleep(100); +} + /** * pci_iov_init - initialize the IOV capability * @dev: the PCI device @@ -173,3 +192,13 @@ return dev->sriov->pos + PCI_SRIOV_BAR + 4 * (resno - PCI_IOV_RESOURCES); } + +/** + * pci_restore_iov_state - restore the state of the IOV capability + * @dev: the PCI device + */ +void pci_restore_iov_state(struct pci_dev *dev) +{ + if (dev->is_physfn) + sriov_restore_state(dev); +} diff -r 92730fa71044 -r 2629935bf356 drivers/pci/pci.c --- a/drivers/pci/pci.c Tue Mar 17 01:43:05 2009 -0400 +++ b/drivers/pci/pci.c Tue Mar 17 01:45:42 2009 -0400 @@ -562,6 +562,8 @@ pci_restore_pcix_state(dev); pci_restore_msi_state(dev); pci_restore_msix_state(dev); + pci_restore_iov_state(dev); + return 0; } diff -r 92730fa71044 -r 2629935bf356 drivers/pci/pci.h --- a/drivers/pci/pci.h Tue Mar 17 01:43:05 2009 -0400 +++ b/drivers/pci/pci.h Tue Mar 17 01:45:42 2009 -0400 @@ -154,6 +154,7 @@ extern void pci_iov_release(struct pci_dev *dev); extern int pci_iov_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type); +extern void pci_restore_iov_state(struct pci_dev *dev); #else static inline int pci_iov_init(struct pci_dev *dev) { @@ -168,4 +169,7 @@ { return 0; } +static inline void pci_restore_iov_state(struct pci_dev *dev) +{ +} #endif /* CONFIG_PCI_IOV */