diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/dmar.c | 7 | ||||
-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/intel-iommu.c | 14 | ||||
-rw-r--r-- | drivers/pci/intr_remapping.c | 1 | ||||
-rw-r--r-- | drivers/pci/msi.c | 29 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 266 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 4 | ||||
-rw-r--r-- | drivers/pci/pci.c | 63 | ||||
-rw-r--r-- | drivers/pci/pci.h | 6 | ||||
-rw-r--r-- | drivers/pci/pcie/aspm.c | 4 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv_pci.c | 16 | ||||
-rw-r--r-- | drivers/pci/rom.c | 8 |
14 files changed, 289 insertions, 181 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index f5a662a50acb..519f5f91e765 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -42,6 +42,7 @@ | |||
42 | LIST_HEAD(dmar_drhd_units); | 42 | LIST_HEAD(dmar_drhd_units); |
43 | 43 | ||
44 | static struct acpi_table_header * __initdata dmar_tbl; | 44 | static struct acpi_table_header * __initdata dmar_tbl; |
45 | static acpi_size dmar_tbl_size; | ||
45 | 46 | ||
46 | static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd) | 47 | static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd) |
47 | { | 48 | { |
@@ -288,8 +289,9 @@ static int __init dmar_table_detect(void) | |||
288 | acpi_status status = AE_OK; | 289 | acpi_status status = AE_OK; |
289 | 290 | ||
290 | /* if we could find DMAR table, then there are DMAR devices */ | 291 | /* if we could find DMAR table, then there are DMAR devices */ |
291 | status = acpi_get_table(ACPI_SIG_DMAR, 0, | 292 | status = acpi_get_table_with_size(ACPI_SIG_DMAR, 0, |
292 | (struct acpi_table_header **)&dmar_tbl); | 293 | (struct acpi_table_header **)&dmar_tbl, |
294 | &dmar_tbl_size); | ||
293 | 295 | ||
294 | if (ACPI_SUCCESS(status) && !dmar_tbl) { | 296 | if (ACPI_SUCCESS(status) && !dmar_tbl) { |
295 | printk (KERN_WARNING PREFIX "Unable to map DMAR\n"); | 297 | printk (KERN_WARNING PREFIX "Unable to map DMAR\n"); |
@@ -481,6 +483,7 @@ void __init detect_intel_iommu(void) | |||
481 | iommu_detected = 1; | 483 | iommu_detected = 1; |
482 | #endif | 484 | #endif |
483 | } | 485 | } |
486 | early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size); | ||
484 | dmar_tbl = NULL; | 487 | dmar_tbl = NULL; |
485 | } | 488 | } |
486 | 489 | ||
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/intel-iommu.c b/drivers/pci/intel-iommu.c index 3dfecb20d5e7..f4b7c79023ff 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -268,7 +268,12 @@ static long list_size; | |||
268 | 268 | ||
269 | static void domain_remove_dev_info(struct dmar_domain *domain); | 269 | static void domain_remove_dev_info(struct dmar_domain *domain); |
270 | 270 | ||
271 | int dmar_disabled; | 271 | #ifdef CONFIG_DMAR_DEFAULT_ON |
272 | int dmar_disabled = 0; | ||
273 | #else | ||
274 | int dmar_disabled = 1; | ||
275 | #endif /*CONFIG_DMAR_DEFAULT_ON*/ | ||
276 | |||
272 | static int __initdata dmar_map_gfx = 1; | 277 | static int __initdata dmar_map_gfx = 1; |
273 | static int dmar_forcedac; | 278 | static int dmar_forcedac; |
274 | static int intel_iommu_strict; | 279 | static int intel_iommu_strict; |
@@ -284,9 +289,12 @@ static int __init intel_iommu_setup(char *str) | |||
284 | if (!str) | 289 | if (!str) |
285 | return -EINVAL; | 290 | return -EINVAL; |
286 | while (*str) { | 291 | while (*str) { |
287 | if (!strncmp(str, "off", 3)) { | 292 | if (!strncmp(str, "on", 2)) { |
293 | dmar_disabled = 0; | ||
294 | printk(KERN_INFO "Intel-IOMMU: enabled\n"); | ||
295 | } else if (!strncmp(str, "off", 3)) { | ||
288 | dmar_disabled = 1; | 296 | dmar_disabled = 1; |
289 | printk(KERN_INFO"Intel-IOMMU: disabled\n"); | 297 | printk(KERN_INFO "Intel-IOMMU: disabled\n"); |
290 | } else if (!strncmp(str, "igfx_off", 8)) { | 298 | } else if (!strncmp(str, "igfx_off", 8)) { |
291 | dmar_map_gfx = 0; | 299 | dmar_map_gfx = 0; |
292 | printk(KERN_INFO | 300 | printk(KERN_INFO |
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index f78371b22529..5a57753ea9fc 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/irq.h> | 6 | #include <linux/irq.h> |
7 | #include <asm/io_apic.h> | 7 | #include <asm/io_apic.h> |
8 | #include <asm/smp.h> | 8 | #include <asm/smp.h> |
9 | #include <asm/cpu.h> | ||
9 | #include <linux/intel-iommu.h> | 10 | #include <linux/intel-iommu.h> |
10 | #include "intr_remapping.h" | 11 | #include "intr_remapping.h" |
11 | 12 | ||
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..93eac1423585 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -355,17 +355,34 @@ 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_power_t prev = pci_dev->current_state; | ||
359 | |||
360 | pci_dev->state_saved = false; | ||
361 | |||
358 | i = drv->suspend(pci_dev, state); | 362 | i = drv->suspend(pci_dev, state); |
359 | suspend_report_result(drv->suspend, i); | 363 | suspend_report_result(drv->suspend, i); |
360 | } else { | 364 | if (i) |
361 | pci_save_state(pci_dev); | 365 | return i; |
362 | /* | 366 | |
363 | * This is for compatibility with existing code with legacy PM | 367 | if (pci_dev->state_saved) |
364 | * support. | 368 | goto Fixup; |
365 | */ | 369 | |
366 | pci_pm_set_unknown_state(pci_dev); | 370 | if (pci_dev->current_state != PCI_D0 |
371 | && pci_dev->current_state != PCI_UNKNOWN) { | ||
372 | WARN_ONCE(pci_dev->current_state != prev, | ||
373 | "PCI PM: Device state not saved by %pF\n", | ||
374 | drv->suspend); | ||
375 | goto Fixup; | ||
376 | } | ||
367 | } | 377 | } |
368 | 378 | ||
379 | pci_save_state(pci_dev); | ||
380 | /* | ||
381 | * This is for compatibility with existing code with legacy PM support. | ||
382 | */ | ||
383 | pci_pm_set_unknown_state(pci_dev); | ||
384 | |||
385 | Fixup: | ||
369 | pci_fixup_device(pci_fixup_suspend, pci_dev); | 386 | pci_fixup_device(pci_fixup_suspend, pci_dev); |
370 | 387 | ||
371 | return i; | 388 | return i; |
@@ -386,108 +403,47 @@ static int pci_legacy_suspend_late(struct device *dev, pm_message_t state) | |||
386 | 403 | ||
387 | static int pci_legacy_resume_early(struct device *dev) | 404 | static int pci_legacy_resume_early(struct device *dev) |
388 | { | 405 | { |
389 | int error = 0; | ||
390 | struct pci_dev * pci_dev = to_pci_dev(dev); | 406 | struct pci_dev * pci_dev = to_pci_dev(dev); |
391 | struct pci_driver * drv = pci_dev->driver; | 407 | struct pci_driver * drv = pci_dev->driver; |
392 | 408 | ||
393 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | 409 | return drv && drv->resume_early ? |
394 | 410 | drv->resume_early(pci_dev) : 0; | |
395 | if (drv && drv->resume_early) | ||
396 | error = drv->resume_early(pci_dev); | ||
397 | return error; | ||
398 | } | 411 | } |
399 | 412 | ||
400 | static int pci_legacy_resume(struct device *dev) | 413 | static int pci_legacy_resume(struct device *dev) |
401 | { | 414 | { |
402 | int error; | ||
403 | struct pci_dev * pci_dev = to_pci_dev(dev); | 415 | struct pci_dev * pci_dev = to_pci_dev(dev); |
404 | struct pci_driver * drv = pci_dev->driver; | 416 | struct pci_driver * drv = pci_dev->driver; |
405 | 417 | ||
406 | pci_fixup_device(pci_fixup_resume, pci_dev); | 418 | pci_fixup_device(pci_fixup_resume, pci_dev); |
407 | 419 | ||
408 | if (drv && drv->resume) { | 420 | return drv && drv->resume ? |
409 | error = drv->resume(pci_dev); | 421 | 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 | } | 422 | } |
417 | 423 | ||
418 | /* Auxiliary functions used by the new power management framework */ | 424 | /* Auxiliary functions used by the new power management framework */ |
419 | 425 | ||
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) | 426 | static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev) |
446 | { | 427 | { |
447 | if (pci_restore_standard_config(pci_dev)) | 428 | pci_restore_standard_config(pci_dev); |
448 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | 429 | pci_dev->state_saved = false; |
430 | pci_fixup_device(pci_fixup_resume_early, pci_dev); | ||
449 | } | 431 | } |
450 | 432 | ||
451 | static int pci_pm_default_resume(struct pci_dev *pci_dev) | 433 | static void pci_pm_default_resume(struct pci_dev *pci_dev) |
452 | { | 434 | { |
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); | 435 | pci_fixup_device(pci_fixup_resume, pci_dev); |
465 | 436 | ||
466 | if (!pci_is_bridge(pci_dev)) | 437 | if (!pci_is_bridge(pci_dev)) |
467 | pci_enable_wake(pci_dev, PCI_D0, false); | 438 | pci_enable_wake(pci_dev, PCI_D0, false); |
468 | |||
469 | return pci_pm_reenable_device(pci_dev); | ||
470 | } | ||
471 | |||
472 | static void pci_pm_default_suspend_generic(struct pci_dev *pci_dev) | ||
473 | { | ||
474 | /* If device is enabled at this point, disable it */ | ||
475 | pci_disable_enabled_device(pci_dev); | ||
476 | /* | ||
477 | * Save state with interrupts enabled, because in principle the bus the | ||
478 | * device is on may be put into a low power state after this code runs. | ||
479 | */ | ||
480 | pci_save_state(pci_dev); | ||
481 | } | 439 | } |
482 | 440 | ||
483 | static void pci_pm_default_suspend(struct pci_dev *pci_dev) | 441 | static void pci_pm_default_suspend(struct pci_dev *pci_dev) |
484 | { | 442 | { |
485 | pci_pm_default_suspend_generic(pci_dev); | 443 | /* Disable non-bridge devices without PM support */ |
486 | |||
487 | if (!pci_is_bridge(pci_dev)) | 444 | if (!pci_is_bridge(pci_dev)) |
488 | pci_prepare_to_sleep(pci_dev); | 445 | pci_disable_enabled_device(pci_dev); |
489 | 446 | pci_save_state(pci_dev); | |
490 | pci_fixup_device(pci_fixup_suspend, pci_dev); | ||
491 | } | 447 | } |
492 | 448 | ||
493 | static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) | 449 | static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) |
@@ -532,21 +488,49 @@ static void pci_pm_complete(struct device *dev) | |||
532 | static int pci_pm_suspend(struct device *dev) | 488 | static int pci_pm_suspend(struct device *dev) |
533 | { | 489 | { |
534 | struct pci_dev *pci_dev = to_pci_dev(dev); | 490 | struct pci_dev *pci_dev = to_pci_dev(dev); |
535 | struct device_driver *drv = dev->driver; | 491 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
536 | int error = 0; | ||
537 | 492 | ||
538 | if (pci_has_legacy_pm_support(pci_dev)) | 493 | if (pci_has_legacy_pm_support(pci_dev)) |
539 | return pci_legacy_suspend(dev, PMSG_SUSPEND); | 494 | return pci_legacy_suspend(dev, PMSG_SUSPEND); |
540 | 495 | ||
541 | if (drv && drv->pm && drv->pm->suspend) { | 496 | if (!pm) { |
542 | error = drv->pm->suspend(dev); | 497 | pci_pm_default_suspend(pci_dev); |
543 | suspend_report_result(drv->pm->suspend, error); | 498 | goto Fixup; |
544 | } | 499 | } |
545 | 500 | ||
546 | if (!error) | 501 | pci_dev->state_saved = false; |
547 | pci_pm_default_suspend(pci_dev); | ||
548 | 502 | ||
549 | return error; | 503 | if (pm->suspend) { |
504 | pci_power_t prev = pci_dev->current_state; | ||
505 | int error; | ||
506 | |||
507 | error = pm->suspend(dev); | ||
508 | suspend_report_result(pm->suspend, error); | ||
509 | if (error) | ||
510 | return error; | ||
511 | |||
512 | if (pci_dev->state_saved) | ||
513 | goto Fixup; | ||
514 | |||
515 | if (pci_dev->current_state != PCI_D0 | ||
516 | && pci_dev->current_state != PCI_UNKNOWN) { | ||
517 | WARN_ONCE(pci_dev->current_state != prev, | ||
518 | "PCI PM: State of device not saved by %pF\n", | ||
519 | pm->suspend); | ||
520 | goto Fixup; | ||
521 | } | ||
522 | } | ||
523 | |||
524 | if (!pci_dev->state_saved) { | ||
525 | pci_save_state(pci_dev); | ||
526 | if (!pci_is_bridge(pci_dev)) | ||
527 | pci_prepare_to_sleep(pci_dev); | ||
528 | } | ||
529 | |||
530 | Fixup: | ||
531 | pci_fixup_device(pci_fixup_suspend, pci_dev); | ||
532 | |||
533 | return 0; | ||
550 | } | 534 | } |
551 | 535 | ||
552 | static int pci_pm_suspend_noirq(struct device *dev) | 536 | static int pci_pm_suspend_noirq(struct device *dev) |
@@ -575,11 +559,11 @@ static int pci_pm_resume_noirq(struct device *dev) | |||
575 | struct device_driver *drv = dev->driver; | 559 | struct device_driver *drv = dev->driver; |
576 | int error = 0; | 560 | int error = 0; |
577 | 561 | ||
562 | pci_pm_default_resume_noirq(pci_dev); | ||
563 | |||
578 | if (pci_has_legacy_pm_support(pci_dev)) | 564 | if (pci_has_legacy_pm_support(pci_dev)) |
579 | return pci_legacy_resume_early(dev); | 565 | return pci_legacy_resume_early(dev); |
580 | 566 | ||
581 | pci_pm_default_resume_noirq(pci_dev); | ||
582 | |||
583 | if (drv && drv->pm && drv->pm->resume_noirq) | 567 | if (drv && drv->pm && drv->pm->resume_noirq) |
584 | error = drv->pm->resume_noirq(dev); | 568 | error = drv->pm->resume_noirq(dev); |
585 | 569 | ||
@@ -589,18 +573,29 @@ static int pci_pm_resume_noirq(struct device *dev) | |||
589 | static int pci_pm_resume(struct device *dev) | 573 | static int pci_pm_resume(struct device *dev) |
590 | { | 574 | { |
591 | struct pci_dev *pci_dev = to_pci_dev(dev); | 575 | struct pci_dev *pci_dev = to_pci_dev(dev); |
592 | struct device_driver *drv = dev->driver; | 576 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
593 | int error = 0; | 577 | int error = 0; |
594 | 578 | ||
579 | /* | ||
580 | * This is necessary for the suspend error path in which resume is | ||
581 | * called without restoring the standard config registers of the device. | ||
582 | */ | ||
583 | if (pci_dev->state_saved) | ||
584 | pci_restore_standard_config(pci_dev); | ||
585 | |||
595 | if (pci_has_legacy_pm_support(pci_dev)) | 586 | if (pci_has_legacy_pm_support(pci_dev)) |
596 | return pci_legacy_resume(dev); | 587 | return pci_legacy_resume(dev); |
597 | 588 | ||
598 | error = pci_pm_default_resume(pci_dev); | 589 | pci_pm_default_resume(pci_dev); |
599 | 590 | ||
600 | if (!error && drv && drv->pm && drv->pm->resume) | 591 | if (pm) { |
601 | error = drv->pm->resume(dev); | 592 | if (pm->resume) |
593 | error = pm->resume(dev); | ||
594 | } else { | ||
595 | pci_pm_reenable_device(pci_dev); | ||
596 | } | ||
602 | 597 | ||
603 | return error; | 598 | return 0; |
604 | } | 599 | } |
605 | 600 | ||
606 | #else /* !CONFIG_SUSPEND */ | 601 | #else /* !CONFIG_SUSPEND */ |
@@ -617,21 +612,31 @@ static int pci_pm_resume(struct device *dev) | |||
617 | static int pci_pm_freeze(struct device *dev) | 612 | static int pci_pm_freeze(struct device *dev) |
618 | { | 613 | { |
619 | struct pci_dev *pci_dev = to_pci_dev(dev); | 614 | struct pci_dev *pci_dev = to_pci_dev(dev); |
620 | struct device_driver *drv = dev->driver; | 615 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
621 | int error = 0; | ||
622 | 616 | ||
623 | if (pci_has_legacy_pm_support(pci_dev)) | 617 | if (pci_has_legacy_pm_support(pci_dev)) |
624 | return pci_legacy_suspend(dev, PMSG_FREEZE); | 618 | return pci_legacy_suspend(dev, PMSG_FREEZE); |
625 | 619 | ||
626 | if (drv && drv->pm && drv->pm->freeze) { | 620 | if (!pm) { |
627 | error = drv->pm->freeze(dev); | 621 | pci_pm_default_suspend(pci_dev); |
628 | suspend_report_result(drv->pm->freeze, error); | 622 | return 0; |
629 | } | 623 | } |
630 | 624 | ||
631 | if (!error) | 625 | pci_dev->state_saved = false; |
632 | pci_pm_default_suspend_generic(pci_dev); | ||
633 | 626 | ||
634 | return error; | 627 | if (pm->freeze) { |
628 | int error; | ||
629 | |||
630 | error = pm->freeze(dev); | ||
631 | suspend_report_result(pm->freeze, error); | ||
632 | if (error) | ||
633 | return error; | ||
634 | } | ||
635 | |||
636 | if (!pci_dev->state_saved) | ||
637 | pci_save_state(pci_dev); | ||
638 | |||
639 | return 0; | ||
635 | } | 640 | } |
636 | 641 | ||
637 | static int pci_pm_freeze_noirq(struct device *dev) | 642 | static int pci_pm_freeze_noirq(struct device *dev) |
@@ -674,16 +679,18 @@ static int pci_pm_thaw_noirq(struct device *dev) | |||
674 | static int pci_pm_thaw(struct device *dev) | 679 | static int pci_pm_thaw(struct device *dev) |
675 | { | 680 | { |
676 | struct pci_dev *pci_dev = to_pci_dev(dev); | 681 | struct pci_dev *pci_dev = to_pci_dev(dev); |
677 | struct device_driver *drv = dev->driver; | 682 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
678 | int error = 0; | 683 | int error = 0; |
679 | 684 | ||
680 | if (pci_has_legacy_pm_support(pci_dev)) | 685 | if (pci_has_legacy_pm_support(pci_dev)) |
681 | return pci_legacy_resume(dev); | 686 | return pci_legacy_resume(dev); |
682 | 687 | ||
683 | pci_pm_reenable_device(pci_dev); | 688 | if (pm) { |
684 | 689 | if (pm->thaw) | |
685 | if (drv && drv->pm && drv->pm->thaw) | 690 | error = pm->thaw(dev); |
686 | error = drv->pm->thaw(dev); | 691 | } else { |
692 | pci_pm_reenable_device(pci_dev); | ||
693 | } | ||
687 | 694 | ||
688 | return error; | 695 | return error; |
689 | } | 696 | } |
@@ -691,19 +698,29 @@ static int pci_pm_thaw(struct device *dev) | |||
691 | static int pci_pm_poweroff(struct device *dev) | 698 | static int pci_pm_poweroff(struct device *dev) |
692 | { | 699 | { |
693 | struct pci_dev *pci_dev = to_pci_dev(dev); | 700 | struct pci_dev *pci_dev = to_pci_dev(dev); |
694 | struct device_driver *drv = dev->driver; | 701 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
695 | int error = 0; | 702 | int error = 0; |
696 | 703 | ||
697 | if (pci_has_legacy_pm_support(pci_dev)) | 704 | if (pci_has_legacy_pm_support(pci_dev)) |
698 | return pci_legacy_suspend(dev, PMSG_HIBERNATE); | 705 | return pci_legacy_suspend(dev, PMSG_HIBERNATE); |
699 | 706 | ||
700 | if (drv && drv->pm && drv->pm->poweroff) { | 707 | if (!pm) { |
701 | error = drv->pm->poweroff(dev); | 708 | pci_pm_default_suspend(pci_dev); |
702 | suspend_report_result(drv->pm->poweroff, error); | 709 | goto Fixup; |
703 | } | 710 | } |
704 | 711 | ||
705 | if (!error) | 712 | pci_dev->state_saved = false; |
706 | pci_pm_default_suspend(pci_dev); | 713 | |
714 | if (pm->poweroff) { | ||
715 | error = pm->poweroff(dev); | ||
716 | suspend_report_result(pm->poweroff, error); | ||
717 | } | ||
718 | |||
719 | if (!pci_dev->state_saved && !pci_is_bridge(pci_dev)) | ||
720 | pci_prepare_to_sleep(pci_dev); | ||
721 | |||
722 | Fixup: | ||
723 | pci_fixup_device(pci_fixup_suspend, pci_dev); | ||
707 | 724 | ||
708 | return error; | 725 | return error; |
709 | } | 726 | } |
@@ -730,11 +747,11 @@ static int pci_pm_restore_noirq(struct device *dev) | |||
730 | struct device_driver *drv = dev->driver; | 747 | struct device_driver *drv = dev->driver; |
731 | int error = 0; | 748 | int error = 0; |
732 | 749 | ||
750 | pci_pm_default_resume_noirq(pci_dev); | ||
751 | |||
733 | if (pci_has_legacy_pm_support(pci_dev)) | 752 | if (pci_has_legacy_pm_support(pci_dev)) |
734 | return pci_legacy_resume_early(dev); | 753 | return pci_legacy_resume_early(dev); |
735 | 754 | ||
736 | pci_pm_default_resume_noirq(pci_dev); | ||
737 | |||
738 | if (drv && drv->pm && drv->pm->restore_noirq) | 755 | if (drv && drv->pm && drv->pm->restore_noirq) |
739 | error = drv->pm->restore_noirq(dev); | 756 | error = drv->pm->restore_noirq(dev); |
740 | 757 | ||
@@ -744,16 +761,27 @@ static int pci_pm_restore_noirq(struct device *dev) | |||
744 | static int pci_pm_restore(struct device *dev) | 761 | static int pci_pm_restore(struct device *dev) |
745 | { | 762 | { |
746 | struct pci_dev *pci_dev = to_pci_dev(dev); | 763 | struct pci_dev *pci_dev = to_pci_dev(dev); |
747 | struct device_driver *drv = dev->driver; | 764 | struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
748 | int error = 0; | 765 | int error = 0; |
749 | 766 | ||
767 | /* | ||
768 | * This is necessary for the hibernation error path in which restore is | ||
769 | * called without restoring the standard config registers of the device. | ||
770 | */ | ||
771 | if (pci_dev->state_saved) | ||
772 | pci_restore_standard_config(pci_dev); | ||
773 | |||
750 | if (pci_has_legacy_pm_support(pci_dev)) | 774 | if (pci_has_legacy_pm_support(pci_dev)) |
751 | return pci_legacy_resume(dev); | 775 | return pci_legacy_resume(dev); |
752 | 776 | ||
753 | error = pci_pm_default_resume(pci_dev); | 777 | pci_pm_default_resume(pci_dev); |
754 | 778 | ||
755 | if (!error && drv && drv->pm && drv->pm->restore) | 779 | if (pm) { |
756 | error = drv->pm->restore(dev); | 780 | if (pm->restore) |
781 | error = pm->restore(dev); | ||
782 | } else { | ||
783 | pci_pm_reenable_device(pci_dev); | ||
784 | } | ||
757 | 785 | ||
758 | return error; | 786 | return error; |
759 | } | 787 | } |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index db7ec14fa719..dfc4e0ddf241 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -768,8 +768,8 @@ pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
768 | return -EINVAL; | 768 | return -EINVAL; |
769 | 769 | ||
770 | rom = pci_map_rom(pdev, &size); /* size starts out as PCI window size */ | 770 | rom = pci_map_rom(pdev, &size); /* size starts out as PCI window size */ |
771 | if (!rom) | 771 | if (!rom || !size) |
772 | return 0; | 772 | return -EIO; |
773 | 773 | ||
774 | if (off >= size) | 774 | if (off >= size) |
775 | count = 0; | 775 | count = 0; |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e491fdedf705..e3efe6b19ee7 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 | pci_update_current_state(dev, PCI_D0); | ||
1422 | |||
1423 | Restore: | ||
1424 | return dev->state_saved ? pci_restore_state(dev) : 0; | ||
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); |
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 586b6f75910d..b0367f168af4 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -718,9 +718,9 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) | |||
718 | 718 | ||
719 | /* | 719 | /* |
720 | * All PCIe functions are in one slot, remove one function will remove | 720 | * All PCIe functions are in one slot, remove one function will remove |
721 | * the the whole slot, so just wait | 721 | * the whole slot, so just wait until we are the last function left. |
722 | */ | 722 | */ |
723 | if (!list_empty(&parent->subordinate->devices)) | 723 | if (!list_is_last(&pdev->bus_list, &parent->subordinate->devices)) |
724 | goto out; | 724 | goto out; |
725 | 725 | ||
726 | /* All functions are removed, so just disable ASPM for the link */ | 726 | /* All functions are removed, so just disable ASPM for the link */ |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 99a914a027f8..f9b874eaeb9f 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
@@ -55,25 +55,13 @@ static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state) | |||
55 | 55 | ||
56 | } | 56 | } |
57 | 57 | ||
58 | static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state) | ||
59 | { | ||
60 | return pci_save_state(dev); | ||
61 | } | ||
62 | |||
63 | static int pcie_portdrv_resume_early(struct pci_dev *dev) | ||
64 | { | ||
65 | return pci_restore_state(dev); | ||
66 | } | ||
67 | |||
68 | static int pcie_portdrv_resume(struct pci_dev *dev) | 58 | static int pcie_portdrv_resume(struct pci_dev *dev) |
69 | { | 59 | { |
70 | pcie_portdrv_restore_config(dev); | 60 | pci_set_master(dev); |
71 | return pcie_port_device_resume(dev); | 61 | return pcie_port_device_resume(dev); |
72 | } | 62 | } |
73 | #else | 63 | #else |
74 | #define pcie_portdrv_suspend NULL | 64 | #define pcie_portdrv_suspend NULL |
75 | #define pcie_portdrv_suspend_late NULL | ||
76 | #define pcie_portdrv_resume_early NULL | ||
77 | #define pcie_portdrv_resume NULL | 65 | #define pcie_portdrv_resume NULL |
78 | #endif | 66 | #endif |
79 | 67 | ||
@@ -292,8 +280,6 @@ static struct pci_driver pcie_portdriver = { | |||
292 | .remove = pcie_portdrv_remove, | 280 | .remove = pcie_portdrv_remove, |
293 | 281 | ||
294 | .suspend = pcie_portdrv_suspend, | 282 | .suspend = pcie_portdrv_suspend, |
295 | .suspend_late = pcie_portdrv_suspend_late, | ||
296 | .resume_early = pcie_portdrv_resume_early, | ||
297 | .resume = pcie_portdrv_resume, | 283 | .resume = pcie_portdrv_resume, |
298 | 284 | ||
299 | .err_handler = &pcie_portdrv_err_handler, | 285 | .err_handler = &pcie_portdrv_err_handler, |
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index 132a78159b60..29cbe47f219f 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c | |||
@@ -63,7 +63,7 @@ void pci_disable_rom(struct pci_dev *pdev) | |||
63 | * The PCI window size could be much larger than the | 63 | * The PCI window size could be much larger than the |
64 | * actual image size. | 64 | * actual image size. |
65 | */ | 65 | */ |
66 | size_t pci_get_rom_size(void __iomem *rom, size_t size) | 66 | size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size) |
67 | { | 67 | { |
68 | void __iomem *image; | 68 | void __iomem *image; |
69 | int last_image; | 69 | int last_image; |
@@ -72,8 +72,10 @@ size_t pci_get_rom_size(void __iomem *rom, size_t size) | |||
72 | do { | 72 | do { |
73 | void __iomem *pds; | 73 | void __iomem *pds; |
74 | /* Standard PCI ROMs start out with these bytes 55 AA */ | 74 | /* Standard PCI ROMs start out with these bytes 55 AA */ |
75 | if (readb(image) != 0x55) | 75 | if (readb(image) != 0x55) { |
76 | dev_err(&pdev->dev, "Invalid ROM contents\n"); | ||
76 | break; | 77 | break; |
78 | } | ||
77 | if (readb(image + 1) != 0xAA) | 79 | if (readb(image + 1) != 0xAA) |
78 | break; | 80 | break; |
79 | /* get the PCI data structure and check its signature */ | 81 | /* get the PCI data structure and check its signature */ |
@@ -159,7 +161,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) | |||
159 | * size is much larger than the actual size of the ROM. | 161 | * size is much larger than the actual size of the ROM. |
160 | * True size is important if the ROM is going to be copied. | 162 | * True size is important if the ROM is going to be copied. |
161 | */ | 163 | */ |
162 | *size = pci_get_rom_size(rom, *size); | 164 | *size = pci_get_rom_size(pdev, rom, *size); |
163 | return rom; | 165 | return rom; |
164 | } | 166 | } |
165 | 167 | ||