aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c71
1 files changed, 49 insertions, 22 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 815674415267..111569ccab43 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -967,16 +967,59 @@ pci_save_state(struct pci_dev *dev)
967 return 0; 967 return 0;
968} 968}
969 969
970static void pci_restore_config_dword(struct pci_dev *pdev, int offset,
971 u32 saved_val, int retry)
972{
973 u32 val;
974
975 pci_read_config_dword(pdev, offset, &val);
976 if (val == saved_val)
977 return;
978
979 for (;;) {
980 dev_dbg(&pdev->dev, "restoring config space at offset "
981 "%#x (was %#x, writing %#x)\n", offset, val, saved_val);
982 pci_write_config_dword(pdev, offset, saved_val);
983 if (retry-- <= 0)
984 return;
985
986 pci_read_config_dword(pdev, offset, &val);
987 if (val == saved_val)
988 return;
989
990 mdelay(1);
991 }
992}
993
994static void pci_restore_config_space_range(struct pci_dev *pdev,
995 int start, int end, int retry)
996{
997 int index;
998
999 for (index = end; index >= start; index--)
1000 pci_restore_config_dword(pdev, 4 * index,
1001 pdev->saved_config_space[index],
1002 retry);
1003}
1004
1005static void pci_restore_config_space(struct pci_dev *pdev)
1006{
1007 if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
1008 pci_restore_config_space_range(pdev, 10, 15, 0);
1009 /* Restore BARs before the command register. */
1010 pci_restore_config_space_range(pdev, 4, 9, 10);
1011 pci_restore_config_space_range(pdev, 0, 3, 0);
1012 } else {
1013 pci_restore_config_space_range(pdev, 0, 15, 0);
1014 }
1015}
1016
970/** 1017/**
971 * pci_restore_state - Restore the saved state of a PCI device 1018 * pci_restore_state - Restore the saved state of a PCI device
972 * @dev: - PCI device that we're dealing with 1019 * @dev: - PCI device that we're dealing with
973 */ 1020 */
974void pci_restore_state(struct pci_dev *dev) 1021void pci_restore_state(struct pci_dev *dev)
975{ 1022{
976 int i;
977 u32 val;
978 int tries;
979
980 if (!dev->state_saved) 1023 if (!dev->state_saved)
981 return; 1024 return;
982 1025
@@ -984,24 +1027,8 @@ void pci_restore_state(struct pci_dev *dev)
984 pci_restore_pcie_state(dev); 1027 pci_restore_pcie_state(dev);
985 pci_restore_ats_state(dev); 1028 pci_restore_ats_state(dev);
986 1029
987 /* 1030 pci_restore_config_space(dev);
988 * The Base Address register should be programmed before the command 1031
989 * register(s)
990 */
991 for (i = 15; i >= 0; i--) {
992 pci_read_config_dword(dev, i * 4, &val);
993 tries = 10;
994 while (tries && val != dev->saved_config_space[i]) {
995 dev_dbg(&dev->dev, "restoring config "
996 "space at offset %#x (was %#x, writing %#x)\n",
997 i, val, (int)dev->saved_config_space[i]);
998 pci_write_config_dword(dev,i * 4,
999 dev->saved_config_space[i]);
1000 pci_read_config_dword(dev, i * 4, &val);
1001 mdelay(10);
1002 tries--;
1003 }
1004 }
1005 pci_restore_pcix_state(dev); 1032 pci_restore_pcix_state(dev);
1006 pci_restore_msi_state(dev); 1033 pci_restore_msi_state(dev);
1007 pci_restore_iov_state(dev); 1034 pci_restore_iov_state(dev);