diff options
| -rw-r--r-- | MAINTAINERS | 1 | ||||
| -rw-r--r-- | drivers/pci/controller/pci-mvebu.c | 52 | ||||
| -rw-r--r-- | drivers/pci/pci.c | 27 |
3 files changed, 67 insertions, 13 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index e2d974963359..48a65c3a4189 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -324,7 +324,6 @@ F: Documentation/ABI/testing/sysfs-bus-acpi | |||
| 324 | F: Documentation/ABI/testing/configfs-acpi | 324 | F: Documentation/ABI/testing/configfs-acpi |
| 325 | F: drivers/pci/*acpi* | 325 | F: drivers/pci/*acpi* |
| 326 | F: drivers/pci/*/*acpi* | 326 | F: drivers/pci/*/*acpi* |
| 327 | F: drivers/pci/*/*/*acpi* | ||
| 328 | F: tools/power/acpi/ | 327 | F: tools/power/acpi/ |
| 329 | 328 | ||
| 330 | ACPI APEI | 329 | ACPI APEI |
diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c index 50eb0729385b..a41d79b8d46a 100644 --- a/drivers/pci/controller/pci-mvebu.c +++ b/drivers/pci/controller/pci-mvebu.c | |||
| @@ -1145,7 +1145,6 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) | |||
| 1145 | { | 1145 | { |
| 1146 | struct device *dev = &pcie->pdev->dev; | 1146 | struct device *dev = &pcie->pdev->dev; |
| 1147 | struct device_node *np = dev->of_node; | 1147 | struct device_node *np = dev->of_node; |
| 1148 | unsigned int i; | ||
| 1149 | int ret; | 1148 | int ret; |
| 1150 | 1149 | ||
| 1151 | INIT_LIST_HEAD(&pcie->resources); | 1150 | INIT_LIST_HEAD(&pcie->resources); |
| @@ -1179,13 +1178,58 @@ static int mvebu_pcie_parse_request_resources(struct mvebu_pcie *pcie) | |||
| 1179 | resource_size(&pcie->io) - 1); | 1178 | resource_size(&pcie->io) - 1); |
| 1180 | pcie->realio.name = "PCI I/O"; | 1179 | pcie->realio.name = "PCI I/O"; |
| 1181 | 1180 | ||
| 1181 | pci_add_resource(&pcie->resources, &pcie->realio); | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | return devm_request_pci_bus_resources(dev, &pcie->resources); | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | /* | ||
| 1188 | * This is a copy of pci_host_probe(), except that it does the I/O | ||
| 1189 | * remap as the last step, once we are sure we won't fail. | ||
| 1190 | * | ||
| 1191 | * It should be removed once the I/O remap error handling issue has | ||
| 1192 | * been sorted out. | ||
| 1193 | */ | ||
| 1194 | static int mvebu_pci_host_probe(struct pci_host_bridge *bridge) | ||
| 1195 | { | ||
| 1196 | struct mvebu_pcie *pcie; | ||
| 1197 | struct pci_bus *bus, *child; | ||
| 1198 | int ret; | ||
| 1199 | |||
| 1200 | ret = pci_scan_root_bus_bridge(bridge); | ||
| 1201 | if (ret < 0) { | ||
| 1202 | dev_err(bridge->dev.parent, "Scanning root bridge failed"); | ||
| 1203 | return ret; | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | pcie = pci_host_bridge_priv(bridge); | ||
| 1207 | if (resource_size(&pcie->io) != 0) { | ||
| 1208 | unsigned int i; | ||
| 1209 | |||
| 1182 | for (i = 0; i < resource_size(&pcie->realio); i += SZ_64K) | 1210 | for (i = 0; i < resource_size(&pcie->realio); i += SZ_64K) |
| 1183 | pci_ioremap_io(i, pcie->io.start + i); | 1211 | pci_ioremap_io(i, pcie->io.start + i); |
| 1212 | } | ||
| 1184 | 1213 | ||
| 1185 | pci_add_resource(&pcie->resources, &pcie->realio); | 1214 | bus = bridge->bus; |
| 1215 | |||
| 1216 | /* | ||
| 1217 | * We insert PCI resources into the iomem_resource and | ||
| 1218 | * ioport_resource trees in either pci_bus_claim_resources() | ||
| 1219 | * or pci_bus_assign_resources(). | ||
| 1220 | */ | ||
| 1221 | if (pci_has_flag(PCI_PROBE_ONLY)) { | ||
| 1222 | pci_bus_claim_resources(bus); | ||
| 1223 | } else { | ||
| 1224 | pci_bus_size_bridges(bus); | ||
| 1225 | pci_bus_assign_resources(bus); | ||
| 1226 | |||
| 1227 | list_for_each_entry(child, &bus->children, node) | ||
| 1228 | pcie_bus_configure_settings(child); | ||
| 1186 | } | 1229 | } |
| 1187 | 1230 | ||
| 1188 | return devm_request_pci_bus_resources(dev, &pcie->resources); | 1231 | pci_bus_add_devices(bus); |
| 1232 | return 0; | ||
| 1189 | } | 1233 | } |
| 1190 | 1234 | ||
| 1191 | static int mvebu_pcie_probe(struct platform_device *pdev) | 1235 | static int mvebu_pcie_probe(struct platform_device *pdev) |
| @@ -1268,7 +1312,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
| 1268 | bridge->align_resource = mvebu_pcie_align_resource; | 1312 | bridge->align_resource = mvebu_pcie_align_resource; |
| 1269 | bridge->msi = pcie->msi; | 1313 | bridge->msi = pcie->msi; |
| 1270 | 1314 | ||
| 1271 | return pci_host_probe(bridge); | 1315 | return mvebu_pci_host_probe(bridge); |
| 1272 | } | 1316 | } |
| 1273 | 1317 | ||
| 1274 | static const struct of_device_id mvebu_pcie_of_match_table[] = { | 1318 | static const struct of_device_id mvebu_pcie_of_match_table[] = { |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 1835f3a7aa8d..51b6c81671c1 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -1289,12 +1289,12 @@ int pci_save_state(struct pci_dev *dev) | |||
| 1289 | EXPORT_SYMBOL(pci_save_state); | 1289 | EXPORT_SYMBOL(pci_save_state); |
| 1290 | 1290 | ||
| 1291 | static void pci_restore_config_dword(struct pci_dev *pdev, int offset, | 1291 | static void pci_restore_config_dword(struct pci_dev *pdev, int offset, |
| 1292 | u32 saved_val, int retry) | 1292 | u32 saved_val, int retry, bool force) |
| 1293 | { | 1293 | { |
| 1294 | u32 val; | 1294 | u32 val; |
| 1295 | 1295 | ||
| 1296 | pci_read_config_dword(pdev, offset, &val); | 1296 | pci_read_config_dword(pdev, offset, &val); |
| 1297 | if (val == saved_val) | 1297 | if (!force && val == saved_val) |
| 1298 | return; | 1298 | return; |
| 1299 | 1299 | ||
| 1300 | for (;;) { | 1300 | for (;;) { |
| @@ -1313,25 +1313,36 @@ static void pci_restore_config_dword(struct pci_dev *pdev, int offset, | |||
| 1313 | } | 1313 | } |
| 1314 | 1314 | ||
| 1315 | static void pci_restore_config_space_range(struct pci_dev *pdev, | 1315 | static void pci_restore_config_space_range(struct pci_dev *pdev, |
| 1316 | int start, int end, int retry) | 1316 | int start, int end, int retry, |
| 1317 | bool force) | ||
| 1317 | { | 1318 | { |
| 1318 | int index; | 1319 | int index; |
| 1319 | 1320 | ||
| 1320 | for (index = end; index >= start; index--) | 1321 | for (index = end; index >= start; index--) |
| 1321 | pci_restore_config_dword(pdev, 4 * index, | 1322 | pci_restore_config_dword(pdev, 4 * index, |
| 1322 | pdev->saved_config_space[index], | 1323 | pdev->saved_config_space[index], |
| 1323 | retry); | 1324 | retry, force); |
| 1324 | } | 1325 | } |
| 1325 | 1326 | ||
| 1326 | static void pci_restore_config_space(struct pci_dev *pdev) | 1327 | static void pci_restore_config_space(struct pci_dev *pdev) |
| 1327 | { | 1328 | { |
| 1328 | if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL) { | 1329 | if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL) { |
| 1329 | pci_restore_config_space_range(pdev, 10, 15, 0); | 1330 | pci_restore_config_space_range(pdev, 10, 15, 0, false); |
| 1330 | /* Restore BARs before the command register. */ | 1331 | /* Restore BARs before the command register. */ |
| 1331 | pci_restore_config_space_range(pdev, 4, 9, 10); | 1332 | pci_restore_config_space_range(pdev, 4, 9, 10, false); |
| 1332 | pci_restore_config_space_range(pdev, 0, 3, 0); | 1333 | pci_restore_config_space_range(pdev, 0, 3, 0, false); |
| 1334 | } else if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | ||
| 1335 | pci_restore_config_space_range(pdev, 12, 15, 0, false); | ||
| 1336 | |||
| 1337 | /* | ||
| 1338 | * Force rewriting of prefetch registers to avoid S3 resume | ||
| 1339 | * issues on Intel PCI bridges that occur when these | ||
| 1340 | * registers are not explicitly written. | ||
| 1341 | */ | ||
| 1342 | pci_restore_config_space_range(pdev, 9, 11, 0, true); | ||
| 1343 | pci_restore_config_space_range(pdev, 0, 8, 0, false); | ||
| 1333 | } else { | 1344 | } else { |
| 1334 | pci_restore_config_space_range(pdev, 0, 15, 0); | 1345 | pci_restore_config_space_range(pdev, 0, 15, 0, false); |
| 1335 | } | 1346 | } |
| 1336 | } | 1347 | } |
| 1337 | 1348 | ||
