diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pci.c | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 815674415267..d20f1334792b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -967,16 +967,47 @@ pci_save_state(struct pci_dev *dev) | |||
967 | return 0; | 967 | return 0; |
968 | } | 968 | } |
969 | 969 | ||
970 | static 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 | |||
994 | static void pci_restore_config_space(struct pci_dev *pdev, int start, int end, | ||
995 | 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 | |||
970 | /** | 1005 | /** |
971 | * pci_restore_state - Restore the saved state of a PCI device | 1006 | * pci_restore_state - Restore the saved state of a PCI device |
972 | * @dev: - PCI device that we're dealing with | 1007 | * @dev: - PCI device that we're dealing with |
973 | */ | 1008 | */ |
974 | void pci_restore_state(struct pci_dev *dev) | 1009 | void pci_restore_state(struct pci_dev *dev) |
975 | { | 1010 | { |
976 | int i; | ||
977 | u32 val; | ||
978 | int tries; | ||
979 | |||
980 | if (!dev->state_saved) | 1011 | if (!dev->state_saved) |
981 | return; | 1012 | return; |
982 | 1013 | ||
@@ -984,24 +1015,14 @@ void pci_restore_state(struct pci_dev *dev) | |||
984 | pci_restore_pcie_state(dev); | 1015 | pci_restore_pcie_state(dev); |
985 | pci_restore_ats_state(dev); | 1016 | pci_restore_ats_state(dev); |
986 | 1017 | ||
1018 | pci_restore_config_space(dev, 10, 15, 0); | ||
987 | /* | 1019 | /* |
988 | * The Base Address register should be programmed before the command | 1020 | * The Base Address register should be programmed before the command |
989 | * register(s) | 1021 | * register(s) |
990 | */ | 1022 | */ |
991 | for (i = 15; i >= 0; i--) { | 1023 | pci_restore_config_space(dev, 4, 9, 10); |
992 | pci_read_config_dword(dev, i * 4, &val); | 1024 | pci_restore_config_space(dev, 0, 3, 0); |
993 | tries = 10; | 1025 | |
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); | 1026 | pci_restore_pcix_state(dev); |
1006 | pci_restore_msi_state(dev); | 1027 | pci_restore_msi_state(dev); |
1007 | pci_restore_iov_state(dev); | 1028 | pci_restore_iov_state(dev); |