diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-26 13:35:27 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-26 13:35:27 -0500 |
commit | 68c6b859846bd078b37c6ca5f3882032f129e72d (patch) | |
tree | e243605957f1cab3532d57d86ea87355c10b6385 /drivers/pci/pci.c | |
parent | a4a47bc03fe520e95e0c4212bf97c86545fb14f9 (diff) | |
parent | bb8d41330ce27edb91adb6922d3f8e1a8923f727 (diff) |
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (48 commits)
x86/PCI: Prevent mmconfig memory corruption
ACPI: Use GPE reference counting to support shared GPEs
x86/PCI: use host bridge _CRS info by default on 2008 and newer machines
PCI: augment bus resource table with a list
PCI: add pci_bus_for_each_resource(), remove direct bus->resource[] refs
PCI: read bridge windows before filling in subtractive decode resources
PCI: split up pci_read_bridge_bases()
PCIe PME: use pci_pcie_cap()
PCI PM: Run-time callbacks for PCI bus type
PCIe PME: use pci_is_pcie()
PCI / ACPI / PM: Platform support for PCI PME wake-up
ACPI / ACPICA: Multiple system notify handlers per device
ACPI / PM: Add more run-time wake-up fields
ACPI: Use GPE reference counting to support shared GPEs
PCI PM: Make it possible to force using INTx for PCIe PME signaling
PCI PM: PCIe PME root port service driver
PCI PM: Add function for checking PME status of devices
PCI: mark is_pcie obsolete
PCI: set PCI_PREF_RANGE_TYPE_64 in pci_bridge_check_ranges
PCI: pciehp: second try to get big range for pcie devices
...
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 157 |
1 files changed, 147 insertions, 10 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 315fea47e784..f4a2738bf0bf 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -19,8 +19,8 @@ | |||
19 | #include <linux/pci-aspm.h> | 19 | #include <linux/pci-aspm.h> |
20 | #include <linux/pm_wakeup.h> | 20 | #include <linux/pm_wakeup.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ | ||
23 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/pm_runtime.h> | ||
24 | #include <asm/setup.h> | 24 | #include <asm/setup.h> |
25 | #include "pci.h" | 25 | #include "pci.h" |
26 | 26 | ||
@@ -29,6 +29,12 @@ const char *pci_power_names[] = { | |||
29 | }; | 29 | }; |
30 | EXPORT_SYMBOL_GPL(pci_power_names); | 30 | EXPORT_SYMBOL_GPL(pci_power_names); |
31 | 31 | ||
32 | int isa_dma_bridge_buggy; | ||
33 | EXPORT_SYMBOL(isa_dma_bridge_buggy); | ||
34 | |||
35 | int pci_pci_problems; | ||
36 | EXPORT_SYMBOL(pci_pci_problems); | ||
37 | |||
32 | unsigned int pci_pm_d3_delay; | 38 | unsigned int pci_pm_d3_delay; |
33 | 39 | ||
34 | static void pci_dev_d3_sleep(struct pci_dev *dev) | 40 | static void pci_dev_d3_sleep(struct pci_dev *dev) |
@@ -380,10 +386,9 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) | |||
380 | { | 386 | { |
381 | const struct pci_bus *bus = dev->bus; | 387 | const struct pci_bus *bus = dev->bus; |
382 | int i; | 388 | int i; |
383 | struct resource *best = NULL; | 389 | struct resource *best = NULL, *r; |
384 | 390 | ||
385 | for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | 391 | pci_bus_for_each_resource(bus, r, i) { |
386 | struct resource *r = bus->resource[i]; | ||
387 | if (!r) | 392 | if (!r) |
388 | continue; | 393 | continue; |
389 | if (res->start && !(res->start >= r->start && res->end <= r->end)) | 394 | if (res->start && !(res->start >= r->start && res->end <= r->end)) |
@@ -457,6 +462,12 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) | |||
457 | pci_platform_pm->sleep_wake(dev, enable) : -ENODEV; | 462 | pci_platform_pm->sleep_wake(dev, enable) : -ENODEV; |
458 | } | 463 | } |
459 | 464 | ||
465 | static inline int platform_pci_run_wake(struct pci_dev *dev, bool enable) | ||
466 | { | ||
467 | return pci_platform_pm ? | ||
468 | pci_platform_pm->run_wake(dev, enable) : -ENODEV; | ||
469 | } | ||
470 | |||
460 | /** | 471 | /** |
461 | * pci_raw_set_power_state - Use PCI PM registers to set the power state of | 472 | * pci_raw_set_power_state - Use PCI PM registers to set the power state of |
462 | * given PCI device | 473 | * given PCI device |
@@ -1190,6 +1201,66 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state) | |||
1190 | } | 1201 | } |
1191 | 1202 | ||
1192 | /** | 1203 | /** |
1204 | * pci_check_pme_status - Check if given device has generated PME. | ||
1205 | * @dev: Device to check. | ||
1206 | * | ||
1207 | * Check the PME status of the device and if set, clear it and clear PME enable | ||
1208 | * (if set). Return 'true' if PME status and PME enable were both set or | ||
1209 | * 'false' otherwise. | ||
1210 | */ | ||
1211 | bool pci_check_pme_status(struct pci_dev *dev) | ||
1212 | { | ||
1213 | int pmcsr_pos; | ||
1214 | u16 pmcsr; | ||
1215 | bool ret = false; | ||
1216 | |||
1217 | if (!dev->pm_cap) | ||
1218 | return false; | ||
1219 | |||
1220 | pmcsr_pos = dev->pm_cap + PCI_PM_CTRL; | ||
1221 | pci_read_config_word(dev, pmcsr_pos, &pmcsr); | ||
1222 | if (!(pmcsr & PCI_PM_CTRL_PME_STATUS)) | ||
1223 | return false; | ||
1224 | |||
1225 | /* Clear PME status. */ | ||
1226 | pmcsr |= PCI_PM_CTRL_PME_STATUS; | ||
1227 | if (pmcsr & PCI_PM_CTRL_PME_ENABLE) { | ||
1228 | /* Disable PME to avoid interrupt flood. */ | ||
1229 | pmcsr &= ~PCI_PM_CTRL_PME_ENABLE; | ||
1230 | ret = true; | ||
1231 | } | ||
1232 | |||
1233 | pci_write_config_word(dev, pmcsr_pos, pmcsr); | ||
1234 | |||
1235 | return ret; | ||
1236 | } | ||
1237 | |||
1238 | /** | ||
1239 | * pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set. | ||
1240 | * @dev: Device to handle. | ||
1241 | * @ign: Ignored. | ||
1242 | * | ||
1243 | * Check if @dev has generated PME and queue a resume request for it in that | ||
1244 | * case. | ||
1245 | */ | ||
1246 | static int pci_pme_wakeup(struct pci_dev *dev, void *ign) | ||
1247 | { | ||
1248 | if (pci_check_pme_status(dev)) | ||
1249 | pm_request_resume(&dev->dev); | ||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1253 | /** | ||
1254 | * pci_pme_wakeup_bus - Walk given bus and wake up devices on it, if necessary. | ||
1255 | * @bus: Top bus of the subtree to walk. | ||
1256 | */ | ||
1257 | void pci_pme_wakeup_bus(struct pci_bus *bus) | ||
1258 | { | ||
1259 | if (bus) | ||
1260 | pci_walk_bus(bus, pci_pme_wakeup, NULL); | ||
1261 | } | ||
1262 | |||
1263 | /** | ||
1193 | * pci_pme_capable - check the capability of PCI device to generate PME# | 1264 | * pci_pme_capable - check the capability of PCI device to generate PME# |
1194 | * @dev: PCI device to handle. | 1265 | * @dev: PCI device to handle. |
1195 | * @state: PCI state from which device will issue PME#. | 1266 | * @state: PCI state from which device will issue PME#. |
@@ -1230,9 +1301,10 @@ void pci_pme_active(struct pci_dev *dev, bool enable) | |||
1230 | } | 1301 | } |
1231 | 1302 | ||
1232 | /** | 1303 | /** |
1233 | * pci_enable_wake - enable PCI device as wakeup event source | 1304 | * __pci_enable_wake - enable PCI device as wakeup event source |
1234 | * @dev: PCI device affected | 1305 | * @dev: PCI device affected |
1235 | * @state: PCI state from which device will issue wakeup events | 1306 | * @state: PCI state from which device will issue wakeup events |
1307 | * @runtime: True if the events are to be generated at run time | ||
1236 | * @enable: True to enable event generation; false to disable | 1308 | * @enable: True to enable event generation; false to disable |
1237 | * | 1309 | * |
1238 | * This enables the device as a wakeup event source, or disables it. | 1310 | * This enables the device as a wakeup event source, or disables it. |
@@ -1248,11 +1320,12 @@ void pci_pme_active(struct pci_dev *dev, bool enable) | |||
1248 | * Error code depending on the platform is returned if both the platform and | 1320 | * Error code depending on the platform is returned if both the platform and |
1249 | * the native mechanism fail to enable the generation of wake-up events | 1321 | * the native mechanism fail to enable the generation of wake-up events |
1250 | */ | 1322 | */ |
1251 | int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable) | 1323 | int __pci_enable_wake(struct pci_dev *dev, pci_power_t state, |
1324 | bool runtime, bool enable) | ||
1252 | { | 1325 | { |
1253 | int ret = 0; | 1326 | int ret = 0; |
1254 | 1327 | ||
1255 | if (enable && !device_may_wakeup(&dev->dev)) | 1328 | if (enable && !runtime && !device_may_wakeup(&dev->dev)) |
1256 | return -EINVAL; | 1329 | return -EINVAL; |
1257 | 1330 | ||
1258 | /* Don't do the same thing twice in a row for one device. */ | 1331 | /* Don't do the same thing twice in a row for one device. */ |
@@ -1272,19 +1345,24 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable) | |||
1272 | pci_pme_active(dev, true); | 1345 | pci_pme_active(dev, true); |
1273 | else | 1346 | else |
1274 | ret = 1; | 1347 | ret = 1; |
1275 | error = platform_pci_sleep_wake(dev, true); | 1348 | error = runtime ? platform_pci_run_wake(dev, true) : |
1349 | platform_pci_sleep_wake(dev, true); | ||
1276 | if (ret) | 1350 | if (ret) |
1277 | ret = error; | 1351 | ret = error; |
1278 | if (!ret) | 1352 | if (!ret) |
1279 | dev->wakeup_prepared = true; | 1353 | dev->wakeup_prepared = true; |
1280 | } else { | 1354 | } else { |
1281 | platform_pci_sleep_wake(dev, false); | 1355 | if (runtime) |
1356 | platform_pci_run_wake(dev, false); | ||
1357 | else | ||
1358 | platform_pci_sleep_wake(dev, false); | ||
1282 | pci_pme_active(dev, false); | 1359 | pci_pme_active(dev, false); |
1283 | dev->wakeup_prepared = false; | 1360 | dev->wakeup_prepared = false; |
1284 | } | 1361 | } |
1285 | 1362 | ||
1286 | return ret; | 1363 | return ret; |
1287 | } | 1364 | } |
1365 | EXPORT_SYMBOL(__pci_enable_wake); | ||
1288 | 1366 | ||
1289 | /** | 1367 | /** |
1290 | * pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold | 1368 | * pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold |
@@ -1394,6 +1472,66 @@ int pci_back_from_sleep(struct pci_dev *dev) | |||
1394 | } | 1472 | } |
1395 | 1473 | ||
1396 | /** | 1474 | /** |
1475 | * pci_finish_runtime_suspend - Carry out PCI-specific part of runtime suspend. | ||
1476 | * @dev: PCI device being suspended. | ||
1477 | * | ||
1478 | * Prepare @dev to generate wake-up events at run time and put it into a low | ||
1479 | * power state. | ||
1480 | */ | ||
1481 | int pci_finish_runtime_suspend(struct pci_dev *dev) | ||
1482 | { | ||
1483 | pci_power_t target_state = pci_target_state(dev); | ||
1484 | int error; | ||
1485 | |||
1486 | if (target_state == PCI_POWER_ERROR) | ||
1487 | return -EIO; | ||
1488 | |||
1489 | __pci_enable_wake(dev, target_state, true, pci_dev_run_wake(dev)); | ||
1490 | |||
1491 | error = pci_set_power_state(dev, target_state); | ||
1492 | |||
1493 | if (error) | ||
1494 | __pci_enable_wake(dev, target_state, true, false); | ||
1495 | |||
1496 | return error; | ||
1497 | } | ||
1498 | |||
1499 | /** | ||
1500 | * pci_dev_run_wake - Check if device can generate run-time wake-up events. | ||
1501 | * @dev: Device to check. | ||
1502 | * | ||
1503 | * Return true if the device itself is cabable of generating wake-up events | ||
1504 | * (through the platform or using the native PCIe PME) or if the device supports | ||
1505 | * PME and one of its upstream bridges can generate wake-up events. | ||
1506 | */ | ||
1507 | bool pci_dev_run_wake(struct pci_dev *dev) | ||
1508 | { | ||
1509 | struct pci_bus *bus = dev->bus; | ||
1510 | |||
1511 | if (device_run_wake(&dev->dev)) | ||
1512 | return true; | ||
1513 | |||
1514 | if (!dev->pme_support) | ||
1515 | return false; | ||
1516 | |||
1517 | while (bus->parent) { | ||
1518 | struct pci_dev *bridge = bus->self; | ||
1519 | |||
1520 | if (device_run_wake(&bridge->dev)) | ||
1521 | return true; | ||
1522 | |||
1523 | bus = bus->parent; | ||
1524 | } | ||
1525 | |||
1526 | /* We have reached the root bus. */ | ||
1527 | if (bus->bridge) | ||
1528 | return device_run_wake(bus->bridge); | ||
1529 | |||
1530 | return false; | ||
1531 | } | ||
1532 | EXPORT_SYMBOL_GPL(pci_dev_run_wake); | ||
1533 | |||
1534 | /** | ||
1397 | * pci_pm_init - Initialize PM functions of given PCI device | 1535 | * pci_pm_init - Initialize PM functions of given PCI device |
1398 | * @dev: PCI device to handle. | 1536 | * @dev: PCI device to handle. |
1399 | */ | 1537 | */ |
@@ -2871,7 +3009,6 @@ EXPORT_SYMBOL(pci_save_state); | |||
2871 | EXPORT_SYMBOL(pci_restore_state); | 3009 | EXPORT_SYMBOL(pci_restore_state); |
2872 | EXPORT_SYMBOL(pci_pme_capable); | 3010 | EXPORT_SYMBOL(pci_pme_capable); |
2873 | EXPORT_SYMBOL(pci_pme_active); | 3011 | EXPORT_SYMBOL(pci_pme_active); |
2874 | EXPORT_SYMBOL(pci_enable_wake); | ||
2875 | EXPORT_SYMBOL(pci_wake_from_d3); | 3012 | EXPORT_SYMBOL(pci_wake_from_d3); |
2876 | EXPORT_SYMBOL(pci_target_state); | 3013 | EXPORT_SYMBOL(pci_target_state); |
2877 | EXPORT_SYMBOL(pci_prepare_to_sleep); | 3014 | EXPORT_SYMBOL(pci_prepare_to_sleep); |