diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/Makefile | 6 | ||||
-rw-r--r-- | drivers/pci/hotplug/fakephp.c | 42 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 4 | ||||
-rw-r--r-- | drivers/pci/msi.c | 29 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 112 | ||||
-rw-r--r-- | drivers/pci/pci.c | 63 | ||||
-rw-r--r-- | drivers/pci/pci.h | 6 |
7 files changed, 162 insertions, 100 deletions
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index e31fb91652ce..2aa117c8cd87 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile | |||
@@ -5,11 +5,15 @@ | |||
5 | obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o | 5 | obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o |
6 | obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o | 6 | obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o |
7 | obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o | 7 | obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o |
8 | |||
9 | # pciehp should be linked before acpiphp in order to allow the native driver | ||
10 | # to attempt to bind first. We can then fall back to generic support. | ||
11 | |||
12 | obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o | ||
8 | obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o | 13 | obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o |
9 | obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o | 14 | obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o |
10 | obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o | 15 | obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o |
11 | obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o | 16 | obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o |
12 | obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o | ||
13 | obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o | 17 | obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o |
14 | obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o | 18 | obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o |
15 | obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o | 19 | obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o |
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index b0e7de9e536d..d8649e127298 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c | |||
@@ -195,13 +195,13 @@ static void remove_slot_worker(struct work_struct *work) | |||
195 | * Tries hard not to re-enable already existing devices; | 195 | * Tries hard not to re-enable already existing devices; |
196 | * also handles scanning of subfunctions. | 196 | * also handles scanning of subfunctions. |
197 | */ | 197 | */ |
198 | static void pci_rescan_slot(struct pci_dev *temp) | 198 | static int pci_rescan_slot(struct pci_dev *temp) |
199 | { | 199 | { |
200 | struct pci_bus *bus = temp->bus; | 200 | struct pci_bus *bus = temp->bus; |
201 | struct pci_dev *dev; | 201 | struct pci_dev *dev; |
202 | int func; | 202 | int func; |
203 | int retval; | ||
204 | u8 hdr_type; | 203 | u8 hdr_type; |
204 | int count = 0; | ||
205 | 205 | ||
206 | if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { | 206 | if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { |
207 | temp->hdr_type = hdr_type & 0x7f; | 207 | temp->hdr_type = hdr_type & 0x7f; |
@@ -213,17 +213,12 @@ static void pci_rescan_slot(struct pci_dev *temp) | |||
213 | dbg("New device on %s function %x:%x\n", | 213 | dbg("New device on %s function %x:%x\n", |
214 | bus->name, temp->devfn >> 3, | 214 | bus->name, temp->devfn >> 3, |
215 | temp->devfn & 7); | 215 | temp->devfn & 7); |
216 | retval = pci_bus_add_device(dev); | 216 | count++; |
217 | if (retval) | ||
218 | dev_err(&dev->dev, "error adding " | ||
219 | "device, continuing.\n"); | ||
220 | else | ||
221 | add_slot(dev); | ||
222 | } | 217 | } |
223 | } | 218 | } |
224 | /* multifunction device? */ | 219 | /* multifunction device? */ |
225 | if (!(hdr_type & 0x80)) | 220 | if (!(hdr_type & 0x80)) |
226 | return; | 221 | return count; |
227 | 222 | ||
228 | /* continue scanning for other functions */ | 223 | /* continue scanning for other functions */ |
229 | for (func = 1, temp->devfn++; func < 8; func++, temp->devfn++) { | 224 | for (func = 1, temp->devfn++; func < 8; func++, temp->devfn++) { |
@@ -239,16 +234,13 @@ static void pci_rescan_slot(struct pci_dev *temp) | |||
239 | dbg("New device on %s function %x:%x\n", | 234 | dbg("New device on %s function %x:%x\n", |
240 | bus->name, temp->devfn >> 3, | 235 | bus->name, temp->devfn >> 3, |
241 | temp->devfn & 7); | 236 | temp->devfn & 7); |
242 | retval = pci_bus_add_device(dev); | 237 | count++; |
243 | if (retval) | ||
244 | dev_err(&dev->dev, "error adding " | ||
245 | "device, continuing.\n"); | ||
246 | else | ||
247 | add_slot(dev); | ||
248 | } | 238 | } |
249 | } | 239 | } |
250 | } | 240 | } |
251 | } | 241 | } |
242 | |||
243 | return count; | ||
252 | } | 244 | } |
253 | 245 | ||
254 | 246 | ||
@@ -262,6 +254,8 @@ static void pci_rescan_bus(const struct pci_bus *bus) | |||
262 | { | 254 | { |
263 | unsigned int devfn; | 255 | unsigned int devfn; |
264 | struct pci_dev *dev; | 256 | struct pci_dev *dev; |
257 | int retval; | ||
258 | int found = 0; | ||
265 | dev = alloc_pci_dev(); | 259 | dev = alloc_pci_dev(); |
266 | if (!dev) | 260 | if (!dev) |
267 | return; | 261 | return; |
@@ -270,7 +264,23 @@ static void pci_rescan_bus(const struct pci_bus *bus) | |||
270 | dev->sysdata = bus->sysdata; | 264 | dev->sysdata = bus->sysdata; |
271 | for (devfn = 0; devfn < 0x100; devfn += 8) { | 265 | for (devfn = 0; devfn < 0x100; devfn += 8) { |
272 | dev->devfn = devfn; | 266 | dev->devfn = devfn; |
273 | pci_rescan_slot(dev); | 267 | found += pci_rescan_slot(dev); |
268 | } | ||
269 | |||
270 | if (found) { | ||
271 | pci_bus_assign_resources(bus); | ||
272 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
273 | /* Skip already-added devices */ | ||
274 | if (dev->is_added) | ||
275 | continue; | ||
276 | retval = pci_bus_add_device(dev); | ||
277 | if (retval) | ||
278 | dev_err(&dev->dev, | ||
279 | "Error adding device, continuing\n"); | ||
280 | else | ||
281 | add_slot(dev); | ||
282 | } | ||
283 | pci_bus_add_devices(bus); | ||
274 | } | 284 | } |
275 | kfree(dev); | 285 | kfree(dev); |
276 | } | 286 | } |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 5482d4ed8256..c2485542f543 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -126,8 +126,10 @@ static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status) | |||
126 | mutex_lock(&slot->ctrl->crit_sect); | 126 | mutex_lock(&slot->ctrl->crit_sect); |
127 | 127 | ||
128 | /* has it been >1 sec since our last toggle? */ | 128 | /* has it been >1 sec since our last toggle? */ |
129 | if ((get_seconds() - slot->last_emi_toggle) < 1) | 129 | if ((get_seconds() - slot->last_emi_toggle) < 1) { |
130 | mutex_unlock(&slot->ctrl->crit_sect); | ||
130 | return -EINVAL; | 131 | return -EINVAL; |
132 | } | ||
131 | 133 | ||
132 | /* see what our current state is */ | 134 | /* see what our current state is */ |
133 | retval = get_lock_status(hotplug_slot, &value); | 135 | retval = get_lock_status(hotplug_slot, &value); |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index b4a90badd0a6..44f15ff70c1d 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -103,6 +103,16 @@ static void msix_set_enable(struct pci_dev *dev, int enable) | |||
103 | } | 103 | } |
104 | } | 104 | } |
105 | 105 | ||
106 | /* | ||
107 | * Essentially, this is ((1 << (1 << x)) - 1), but without the | ||
108 | * undefinedness of a << 32. | ||
109 | */ | ||
110 | static inline __attribute_const__ u32 msi_mask(unsigned x) | ||
111 | { | ||
112 | static const u32 mask[] = { 1, 2, 4, 0xf, 0xff, 0xffff, 0xffffffff }; | ||
113 | return mask[x]; | ||
114 | } | ||
115 | |||
106 | static void msix_flush_writes(struct irq_desc *desc) | 116 | static void msix_flush_writes(struct irq_desc *desc) |
107 | { | 117 | { |
108 | struct msi_desc *entry; | 118 | struct msi_desc *entry; |
@@ -398,21 +408,18 @@ static int msi_capability_init(struct pci_dev *dev) | |||
398 | entry->msi_attrib.masked = 1; | 408 | entry->msi_attrib.masked = 1; |
399 | entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ | 409 | entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ |
400 | entry->msi_attrib.pos = pos; | 410 | entry->msi_attrib.pos = pos; |
401 | if (entry->msi_attrib.maskbit) { | ||
402 | entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos, | ||
403 | entry->msi_attrib.is_64); | ||
404 | } | ||
405 | entry->dev = dev; | 411 | entry->dev = dev; |
406 | if (entry->msi_attrib.maskbit) { | 412 | if (entry->msi_attrib.maskbit) { |
407 | unsigned int maskbits, temp; | 413 | unsigned int base, maskbits, temp; |
414 | |||
415 | base = msi_mask_bits_reg(pos, entry->msi_attrib.is_64); | ||
416 | entry->mask_base = (void __iomem *)(long)base; | ||
417 | |||
408 | /* All MSIs are unmasked by default, Mask them all */ | 418 | /* All MSIs are unmasked by default, Mask them all */ |
409 | pci_read_config_dword(dev, | 419 | pci_read_config_dword(dev, base, &maskbits); |
410 | msi_mask_bits_reg(pos, entry->msi_attrib.is_64), | 420 | temp = msi_mask((control & PCI_MSI_FLAGS_QMASK) >> 1); |
411 | &maskbits); | ||
412 | temp = (1 << multi_msi_capable(control)); | ||
413 | temp = ((temp - 1) & ~temp); | ||
414 | maskbits |= temp; | 421 | maskbits |= temp; |
415 | pci_write_config_dword(dev, entry->msi_attrib.is_64, maskbits); | 422 | pci_write_config_dword(dev, base, maskbits); |
416 | entry->msi_attrib.maskbits_mask = temp; | 423 | entry->msi_attrib.maskbits_mask = temp; |
417 | } | 424 | } |
418 | list_add_tail(&entry->list, &dev->msi_list); | 425 | list_add_tail(&entry->list, &dev->msi_list); |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index c697f2680856..ab1d615425a8 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -355,17 +355,28 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state) | |||
355 | int i = 0; | 355 | int i = 0; |
356 | 356 | ||
357 | if (drv && drv->suspend) { | 357 | if (drv && drv->suspend) { |
358 | pci_dev->state_saved = false; | ||
359 | |||
358 | i = drv->suspend(pci_dev, state); | 360 | i = drv->suspend(pci_dev, state); |
359 | suspend_report_result(drv->suspend, i); | 361 | suspend_report_result(drv->suspend, i); |
360 | } else { | 362 | if (i) |
361 | pci_save_state(pci_dev); | 363 | return i; |
362 | /* | 364 | |
363 | * This is for compatibility with existing code with legacy PM | 365 | if (pci_dev->state_saved) |
364 | * support. | 366 | goto Fixup; |
365 | */ | 367 | |
366 | pci_pm_set_unknown_state(pci_dev); | 368 | if (WARN_ON_ONCE(pci_dev->current_state != PCI_D0)) |
369 | goto Fixup; | ||
367 | } | 370 | } |
368 | 371 | ||
372 | pci_save_state(pci_dev); | ||
373 | pci_dev->state_saved = true; | ||
374 | /* | ||
375 | * This is for compatibility with existing code with legacy PM support. | ||
376 | */ | ||
377 | pci_pm_set_unknown_state(pci_dev); | ||
378 | |||
379 | Fixup: | ||
369 | pci_fixup_device(pci_fixup_suspend, pci_dev); | 380 | pci_fixup_device(pci_fixup_suspend, pci_dev); |
370 | 381 | ||
371 | return i; | 382 | return i; |
@@ -386,81 +397,35 @@ static int pci_legacy_suspend_late(struct device *dev, pm_message_t state) | |||
386 | 397 | ||
387 | static int pci_legacy_resume_early(struct device *dev) | 398 | static int pci_legacy_resume_early(struct device *dev) |
388 | { | 399 | { |
389 | int error = 0; | ||
390 | struct pci_dev * pci_dev = to_pci_dev(dev); | 400 | struct pci_dev * pci_dev = to_pci_dev(dev); |
391 | struct pci_driver * drv = pci_dev->driver; | 401 | struct pci_driver * drv = pci_dev->driver; |
392 | 402 | ||
393 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | 403 | return drv && drv->resume_early ? |
394 | 404 | drv->resume_early(pci_dev) : 0; | |
395 | if (drv && drv->resume_early) | ||
396 | error = drv->resume_early(pci_dev); | ||
397 | return error; | ||
398 | } | 405 | } |
399 | 406 | ||
400 | static int pci_legacy_resume(struct device *dev) | 407 | static int pci_legacy_resume(struct device *dev) |
401 | { | 408 | { |
402 | int error; | ||
403 | struct pci_dev * pci_dev = to_pci_dev(dev); | 409 | struct pci_dev * pci_dev = to_pci_dev(dev); |
404 | struct pci_driver * drv = pci_dev->driver; | 410 | struct pci_driver * drv = pci_dev->driver; |
405 | 411 | ||
406 | pci_fixup_device(pci_fixup_resume, pci_dev); | 412 | pci_fixup_device(pci_fixup_resume, pci_dev); |
407 | 413 | ||
408 | if (drv && drv->resume) { | 414 | return drv && drv->resume ? |
409 | error = drv->resume(pci_dev); | 415 | drv->resume(pci_dev) : pci_pm_reenable_device(pci_dev); |
410 | } else { | ||
411 | /* restore the PCI config space */ | ||
412 | pci_restore_state(pci_dev); | ||
413 | error = pci_pm_reenable_device(pci_dev); | ||
414 | } | ||
415 | return error; | ||
416 | } | 416 | } |
417 | 417 | ||
418 | /* Auxiliary functions used by the new power management framework */ | 418 | /* Auxiliary functions used by the new power management framework */ |
419 | 419 | ||
420 | static int pci_restore_standard_config(struct pci_dev *pci_dev) | ||
421 | { | ||
422 | struct pci_dev *parent = pci_dev->bus->self; | ||
423 | int error = 0; | ||
424 | |||
425 | /* Check if the device's bus is operational */ | ||
426 | if (!parent || parent->current_state == PCI_D0) { | ||
427 | pci_restore_state(pci_dev); | ||
428 | pci_update_current_state(pci_dev, PCI_D0); | ||
429 | } else { | ||
430 | dev_warn(&pci_dev->dev, "unable to restore config, " | ||
431 | "bridge %s in low power state D%d\n", pci_name(parent), | ||
432 | parent->current_state); | ||
433 | pci_dev->current_state = PCI_UNKNOWN; | ||
434 | error = -EAGAIN; | ||
435 | } | ||
436 | |||
437 | return error; | ||
438 | } | ||
439 | |||
440 | static bool pci_is_bridge(struct pci_dev *pci_dev) | ||
441 | { | ||
442 | return !!(pci_dev->subordinate); | ||
443 | } | ||
444 | |||
445 | static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev) | 420 | static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev) |
446 | { | 421 | { |
447 | if (pci_restore_standard_config(pci_dev)) | 422 | pci_restore_standard_config(pci_dev); |
448 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | 423 | pci_dev->state_saved = false; |
424 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | ||
449 | } | 425 | } |
450 | 426 | ||
451 | static int pci_pm_default_resume(struct pci_dev *pci_dev) | 427 | static int pci_pm_default_resume(struct pci_dev *pci_dev) |
452 | { | 428 | { |
453 | /* | ||
454 | * pci_restore_standard_config() should have been called once already, | ||
455 | * but it would have failed if the device's parent bridge had not been | ||
456 | * in power state D0 at that time. Check it and try again if necessary. | ||
457 | */ | ||
458 | if (pci_dev->current_state == PCI_UNKNOWN) { | ||
459 | int error = pci_restore_standard_config(pci_dev); | ||
460 | if (error) | ||
461 | return error; | ||
462 | } | ||
463 | |||
464 | pci_fixup_device(pci_fixup_resume, pci_dev); | 429 | pci_fixup_device(pci_fixup_resume, pci_dev); |
465 | 430 | ||
466 | if (!pci_is_bridge(pci_dev)) | 431 | if (!pci_is_bridge(pci_dev)) |
@@ -575,11 +540,11 @@ static int pci_pm_resume_noirq(struct device *dev) | |||
575 | struct device_driver *drv = dev->driver; | 540 | struct device_driver *drv = dev->driver; |
576 | int error = 0; | 541 | int error = 0; |
577 | 542 | ||
543 | pci_pm_default_resume_noirq(pci_dev); | ||
544 | |||
578 | if (pci_has_legacy_pm_support(pci_dev)) | 545 | if (pci_has_legacy_pm_support(pci_dev)) |
579 | return pci_legacy_resume_early(dev); | 546 | return pci_legacy_resume_early(dev); |
580 | 547 | ||
581 | pci_pm_default_resume_noirq(pci_dev); | ||
582 | |||
583 | if (drv && drv->pm && drv->pm->resume_noirq) | 548 | if (drv && drv->pm && drv->pm->resume_noirq) |
584 | error = drv->pm->resume_noirq(dev); | 549 | error = drv->pm->resume_noirq(dev); |
585 | 550 | ||
@@ -592,6 +557,13 @@ static int pci_pm_resume(struct device *dev) | |||
592 | struct device_driver *drv = dev->driver; | 557 | struct device_driver *drv = dev->driver; |
593 | int error = 0; | 558 | int error = 0; |
594 | 559 | ||
560 | /* | ||
561 | * This is necessary for the suspend error path in which resume is | ||
562 | * called without restoring the standard config registers of the device. | ||
563 | */ | ||
564 | if (pci_dev->state_saved) | ||
565 | pci_restore_standard_config(pci_dev); | ||
566 | |||
595 | if (pci_has_legacy_pm_support(pci_dev)) | 567 | if (pci_has_legacy_pm_support(pci_dev)) |
596 | return pci_legacy_resume(dev); | 568 | return pci_legacy_resume(dev); |
597 | 569 | ||
@@ -697,7 +669,10 @@ static int pci_pm_poweroff(struct device *dev) | |||
697 | if (pci_has_legacy_pm_support(pci_dev)) | 669 | if (pci_has_legacy_pm_support(pci_dev)) |
698 | return pci_legacy_suspend(dev, PMSG_HIBERNATE); | 670 | return pci_legacy_suspend(dev, PMSG_HIBERNATE); |
699 | 671 | ||
700 | if (drv && drv->pm && drv->pm->poweroff) { | 672 | if (!drv || !drv->pm) |
673 | return 0; | ||
674 | |||
675 | if (drv->pm->poweroff) { | ||
701 | error = drv->pm->poweroff(dev); | 676 | error = drv->pm->poweroff(dev); |
702 | suspend_report_result(drv->pm->poweroff, error); | 677 | suspend_report_result(drv->pm->poweroff, error); |
703 | } | 678 | } |
@@ -730,11 +705,11 @@ static int pci_pm_restore_noirq(struct device *dev) | |||
730 | struct device_driver *drv = dev->driver; | 705 | struct device_driver *drv = dev->driver; |
731 | int error = 0; | 706 | int error = 0; |
732 | 707 | ||
708 | pci_pm_default_resume_noirq(pci_dev); | ||
709 | |||
733 | if (pci_has_legacy_pm_support(pci_dev)) | 710 | if (pci_has_legacy_pm_support(pci_dev)) |
734 | return pci_legacy_resume_early(dev); | 711 | return pci_legacy_resume_early(dev); |
735 | 712 | ||
736 | pci_pm_default_resume_noirq(pci_dev); | ||
737 | |||
738 | if (drv && drv->pm && drv->pm->restore_noirq) | 713 | if (drv && drv->pm && drv->pm->restore_noirq) |
739 | error = drv->pm->restore_noirq(dev); | 714 | error = drv->pm->restore_noirq(dev); |
740 | 715 | ||
@@ -747,6 +722,13 @@ static int pci_pm_restore(struct device *dev) | |||
747 | struct device_driver *drv = dev->driver; | 722 | struct device_driver *drv = dev->driver; |
748 | int error = 0; | 723 | int error = 0; |
749 | 724 | ||
725 | /* | ||
726 | * This is necessary for the hibernation error path in which restore is | ||
727 | * called without restoring the standard config registers of the device. | ||
728 | */ | ||
729 | if (pci_dev->state_saved) | ||
730 | pci_restore_standard_config(pci_dev); | ||
731 | |||
750 | if (pci_has_legacy_pm_support(pci_dev)) | 732 | if (pci_has_legacy_pm_support(pci_dev)) |
751 | return pci_legacy_resume(dev); | 733 | return pci_legacy_resume(dev); |
752 | 734 | ||
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e491fdedf705..48807556b47a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ | 22 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ |
23 | #include "pci.h" | 23 | #include "pci.h" |
24 | 24 | ||
25 | unsigned int pci_pm_d3_delay = 10; | 25 | unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT; |
26 | 26 | ||
27 | #ifdef CONFIG_PCI_DOMAINS | 27 | #ifdef CONFIG_PCI_DOMAINS |
28 | int pci_domains_supported = 1; | 28 | int pci_domains_supported = 1; |
@@ -426,6 +426,7 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) | |||
426 | * given PCI device | 426 | * given PCI device |
427 | * @dev: PCI device to handle. | 427 | * @dev: PCI device to handle. |
428 | * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. | 428 | * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. |
429 | * @wait: If 'true', wait for the device to change its power state | ||
429 | * | 430 | * |
430 | * RETURN VALUE: | 431 | * RETURN VALUE: |
431 | * -EINVAL if the requested state is invalid. | 432 | * -EINVAL if the requested state is invalid. |
@@ -435,7 +436,7 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) | |||
435 | * 0 if device's power state has been successfully changed. | 436 | * 0 if device's power state has been successfully changed. |
436 | */ | 437 | */ |
437 | static int | 438 | static int |
438 | pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state) | 439 | pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) |
439 | { | 440 | { |
440 | u16 pmcsr; | 441 | u16 pmcsr; |
441 | bool need_restore = false; | 442 | bool need_restore = false; |
@@ -480,8 +481,10 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
480 | break; | 481 | break; |
481 | case PCI_UNKNOWN: /* Boot-up */ | 482 | case PCI_UNKNOWN: /* Boot-up */ |
482 | if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot | 483 | if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot |
483 | && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) | 484 | && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) { |
484 | need_restore = true; | 485 | need_restore = true; |
486 | wait = true; | ||
487 | } | ||
485 | /* Fall-through: force to D0 */ | 488 | /* Fall-through: force to D0 */ |
486 | default: | 489 | default: |
487 | pmcsr = 0; | 490 | pmcsr = 0; |
@@ -491,12 +494,15 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
491 | /* enter specified state */ | 494 | /* enter specified state */ |
492 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); | 495 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); |
493 | 496 | ||
497 | if (!wait) | ||
498 | return 0; | ||
499 | |||
494 | /* Mandatory power management transition delays */ | 500 | /* Mandatory power management transition delays */ |
495 | /* see PCI PM 1.1 5.6.1 table 18 */ | 501 | /* see PCI PM 1.1 5.6.1 table 18 */ |
496 | if (state == PCI_D3hot || dev->current_state == PCI_D3hot) | 502 | if (state == PCI_D3hot || dev->current_state == PCI_D3hot) |
497 | msleep(pci_pm_d3_delay); | 503 | msleep(pci_pm_d3_delay); |
498 | else if (state == PCI_D2 || dev->current_state == PCI_D2) | 504 | else if (state == PCI_D2 || dev->current_state == PCI_D2) |
499 | udelay(200); | 505 | udelay(PCI_PM_D2_DELAY); |
500 | 506 | ||
501 | dev->current_state = state; | 507 | dev->current_state = state; |
502 | 508 | ||
@@ -515,7 +521,7 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
515 | if (need_restore) | 521 | if (need_restore) |
516 | pci_restore_bars(dev); | 522 | pci_restore_bars(dev); |
517 | 523 | ||
518 | if (dev->bus->self) | 524 | if (wait && dev->bus->self) |
519 | pcie_aspm_pm_state_change(dev->bus->self); | 525 | pcie_aspm_pm_state_change(dev->bus->self); |
520 | 526 | ||
521 | return 0; | 527 | return 0; |
@@ -585,7 +591,7 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
585 | if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) | 591 | if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) |
586 | return 0; | 592 | return 0; |
587 | 593 | ||
588 | error = pci_raw_set_power_state(dev, state); | 594 | error = pci_raw_set_power_state(dev, state, true); |
589 | 595 | ||
590 | if (state > PCI_D0 && platform_pci_power_manageable(dev)) { | 596 | if (state > PCI_D0 && platform_pci_power_manageable(dev)) { |
591 | /* Allow the platform to finalize the transition */ | 597 | /* Allow the platform to finalize the transition */ |
@@ -730,6 +736,7 @@ pci_save_state(struct pci_dev *dev) | |||
730 | /* XXX: 100% dword access ok here? */ | 736 | /* XXX: 100% dword access ok here? */ |
731 | for (i = 0; i < 16; i++) | 737 | for (i = 0; i < 16; i++) |
732 | pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); | 738 | pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]); |
739 | dev->state_saved = true; | ||
733 | if ((i = pci_save_pcie_state(dev)) != 0) | 740 | if ((i = pci_save_pcie_state(dev)) != 0) |
734 | return i; | 741 | return i; |
735 | if ((i = pci_save_pcix_state(dev)) != 0) | 742 | if ((i = pci_save_pcix_state(dev)) != 0) |
@@ -1374,6 +1381,50 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev) | |||
1374 | } | 1381 | } |
1375 | 1382 | ||
1376 | /** | 1383 | /** |
1384 | * pci_restore_standard_config - restore standard config registers of PCI device | ||
1385 | * @dev: PCI device to handle | ||
1386 | * | ||
1387 | * This function assumes that the device's configuration space is accessible. | ||
1388 | * If the device needs to be powered up, the function will wait for it to | ||
1389 | * change the state. | ||
1390 | */ | ||
1391 | int pci_restore_standard_config(struct pci_dev *dev) | ||
1392 | { | ||
1393 | pci_power_t prev_state; | ||
1394 | int error; | ||
1395 | |||
1396 | pci_update_current_state(dev, PCI_D0); | ||
1397 | |||
1398 | prev_state = dev->current_state; | ||
1399 | if (prev_state == PCI_D0) | ||
1400 | goto Restore; | ||
1401 | |||
1402 | error = pci_raw_set_power_state(dev, PCI_D0, false); | ||
1403 | if (error) | ||
1404 | return error; | ||
1405 | |||
1406 | /* | ||
1407 | * This assumes that we won't get a bus in B2 or B3 from the BIOS, but | ||
1408 | * we've made this assumption forever and it appears to be universally | ||
1409 | * satisfied. | ||
1410 | */ | ||
1411 | switch(prev_state) { | ||
1412 | case PCI_D3cold: | ||
1413 | case PCI_D3hot: | ||
1414 | mdelay(pci_pm_d3_delay); | ||
1415 | break; | ||
1416 | case PCI_D2: | ||
1417 | udelay(PCI_PM_D2_DELAY); | ||
1418 | break; | ||
1419 | } | ||
1420 | |||
1421 | dev->current_state = PCI_D0; | ||
1422 | |||
1423 | Restore: | ||
1424 | return pci_restore_state(dev); | ||
1425 | } | ||
1426 | |||
1427 | /** | ||
1377 | * pci_enable_ari - enable ARI forwarding if hardware support it | 1428 | * pci_enable_ari - enable ARI forwarding if hardware support it |
1378 | * @dev: the PCI device | 1429 | * @dev: the PCI device |
1379 | */ | 1430 | */ |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 1351bb4addde..26ddf78ac300 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -49,6 +49,12 @@ extern void pci_disable_enabled_device(struct pci_dev *dev); | |||
49 | extern void pci_pm_init(struct pci_dev *dev); | 49 | extern void pci_pm_init(struct pci_dev *dev); |
50 | extern void platform_pci_wakeup_init(struct pci_dev *dev); | 50 | extern void platform_pci_wakeup_init(struct pci_dev *dev); |
51 | extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); | 51 | extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); |
52 | extern int pci_restore_standard_config(struct pci_dev *dev); | ||
53 | |||
54 | static inline bool pci_is_bridge(struct pci_dev *pci_dev) | ||
55 | { | ||
56 | return !!(pci_dev->subordinate); | ||
57 | } | ||
52 | 58 | ||
53 | extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val); | 59 | extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val); |
54 | extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val); | 60 | extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val); |