diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/Kconfig | 2 | ||||
-rw-r--r-- | drivers/pci/access.c | 41 | ||||
-rw-r--r-- | drivers/pci/dmar.c | 82 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_ibm.c | 5 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_core.c | 5 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_pci.c | 17 | ||||
-rw-r--r-- | drivers/pci/intel-iommu.c | 151 | ||||
-rw-r--r-- | drivers/pci/intr_remapping.c | 6 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 89 | ||||
-rw-r--r-- | drivers/pci/pci.c | 6 | ||||
-rw-r--r-- | drivers/pci/pci.h | 2 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aer_inject.c | 2 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv.c | 179 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv.h | 6 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_core.c | 558 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 21 | ||||
-rw-r--r-- | drivers/pci/setup-bus.c | 114 | ||||
-rw-r--r-- | drivers/pci/slot.c | 48 |
18 files changed, 659 insertions, 675 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 7858a117e80b..34ef70d562b2 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig | |||
@@ -19,7 +19,7 @@ config PCI_MSI | |||
19 | by using the 'pci=nomsi' option. This disables MSI for the | 19 | by using the 'pci=nomsi' option. This disables MSI for the |
20 | entire system. | 20 | entire system. |
21 | 21 | ||
22 | If you don't know what to do here, say N. | 22 | If you don't know what to do here, say Y. |
23 | 23 | ||
24 | config PCI_DEBUG | 24 | config PCI_DEBUG |
25 | bool "PCI Debugging" | 25 | bool "PCI Debugging" |
diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 2f646fe1260f..531bc697d800 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c | |||
@@ -13,7 +13,7 @@ | |||
13 | * configuration space. | 13 | * configuration space. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | static DEFINE_SPINLOCK(pci_lock); | 16 | static DEFINE_RAW_SPINLOCK(pci_lock); |
17 | 17 | ||
18 | /* | 18 | /* |
19 | * Wrappers for all PCI configuration access functions. They just check | 19 | * Wrappers for all PCI configuration access functions. They just check |
@@ -33,10 +33,10 @@ int pci_bus_read_config_##size \ | |||
33 | unsigned long flags; \ | 33 | unsigned long flags; \ |
34 | u32 data = 0; \ | 34 | u32 data = 0; \ |
35 | if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ | 35 | if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ |
36 | spin_lock_irqsave(&pci_lock, flags); \ | 36 | raw_spin_lock_irqsave(&pci_lock, flags); \ |
37 | res = bus->ops->read(bus, devfn, pos, len, &data); \ | 37 | res = bus->ops->read(bus, devfn, pos, len, &data); \ |
38 | *value = (type)data; \ | 38 | *value = (type)data; \ |
39 | spin_unlock_irqrestore(&pci_lock, flags); \ | 39 | raw_spin_unlock_irqrestore(&pci_lock, flags); \ |
40 | return res; \ | 40 | return res; \ |
41 | } | 41 | } |
42 | 42 | ||
@@ -47,9 +47,9 @@ int pci_bus_write_config_##size \ | |||
47 | int res; \ | 47 | int res; \ |
48 | unsigned long flags; \ | 48 | unsigned long flags; \ |
49 | if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ | 49 | if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ |
50 | spin_lock_irqsave(&pci_lock, flags); \ | 50 | raw_spin_lock_irqsave(&pci_lock, flags); \ |
51 | res = bus->ops->write(bus, devfn, pos, len, value); \ | 51 | res = bus->ops->write(bus, devfn, pos, len, value); \ |
52 | spin_unlock_irqrestore(&pci_lock, flags); \ | 52 | raw_spin_unlock_irqrestore(&pci_lock, flags); \ |
53 | return res; \ | 53 | return res; \ |
54 | } | 54 | } |
55 | 55 | ||
@@ -79,10 +79,10 @@ struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops) | |||
79 | struct pci_ops *old_ops; | 79 | struct pci_ops *old_ops; |
80 | unsigned long flags; | 80 | unsigned long flags; |
81 | 81 | ||
82 | spin_lock_irqsave(&pci_lock, flags); | 82 | raw_spin_lock_irqsave(&pci_lock, flags); |
83 | old_ops = bus->ops; | 83 | old_ops = bus->ops; |
84 | bus->ops = ops; | 84 | bus->ops = ops; |
85 | spin_unlock_irqrestore(&pci_lock, flags); | 85 | raw_spin_unlock_irqrestore(&pci_lock, flags); |
86 | return old_ops; | 86 | return old_ops; |
87 | } | 87 | } |
88 | EXPORT_SYMBOL(pci_bus_set_ops); | 88 | EXPORT_SYMBOL(pci_bus_set_ops); |
@@ -136,9 +136,9 @@ static noinline void pci_wait_ucfg(struct pci_dev *dev) | |||
136 | __add_wait_queue(&pci_ucfg_wait, &wait); | 136 | __add_wait_queue(&pci_ucfg_wait, &wait); |
137 | do { | 137 | do { |
138 | set_current_state(TASK_UNINTERRUPTIBLE); | 138 | set_current_state(TASK_UNINTERRUPTIBLE); |
139 | spin_unlock_irq(&pci_lock); | 139 | raw_spin_unlock_irq(&pci_lock); |
140 | schedule(); | 140 | schedule(); |
141 | spin_lock_irq(&pci_lock); | 141 | raw_spin_lock_irq(&pci_lock); |
142 | } while (dev->block_ucfg_access); | 142 | } while (dev->block_ucfg_access); |
143 | __remove_wait_queue(&pci_ucfg_wait, &wait); | 143 | __remove_wait_queue(&pci_ucfg_wait, &wait); |
144 | } | 144 | } |
@@ -150,11 +150,11 @@ int pci_user_read_config_##size \ | |||
150 | int ret = 0; \ | 150 | int ret = 0; \ |
151 | u32 data = -1; \ | 151 | u32 data = -1; \ |
152 | if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ | 152 | if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ |
153 | spin_lock_irq(&pci_lock); \ | 153 | raw_spin_lock_irq(&pci_lock); \ |
154 | if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \ | 154 | if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \ |
155 | ret = dev->bus->ops->read(dev->bus, dev->devfn, \ | 155 | ret = dev->bus->ops->read(dev->bus, dev->devfn, \ |
156 | pos, sizeof(type), &data); \ | 156 | pos, sizeof(type), &data); \ |
157 | spin_unlock_irq(&pci_lock); \ | 157 | raw_spin_unlock_irq(&pci_lock); \ |
158 | *val = (type)data; \ | 158 | *val = (type)data; \ |
159 | return ret; \ | 159 | return ret; \ |
160 | } | 160 | } |
@@ -165,11 +165,11 @@ int pci_user_write_config_##size \ | |||
165 | { \ | 165 | { \ |
166 | int ret = -EIO; \ | 166 | int ret = -EIO; \ |
167 | if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ | 167 | if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ |
168 | spin_lock_irq(&pci_lock); \ | 168 | raw_spin_lock_irq(&pci_lock); \ |
169 | if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \ | 169 | if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \ |
170 | ret = dev->bus->ops->write(dev->bus, dev->devfn, \ | 170 | ret = dev->bus->ops->write(dev->bus, dev->devfn, \ |
171 | pos, sizeof(type), val); \ | 171 | pos, sizeof(type), val); \ |
172 | spin_unlock_irq(&pci_lock); \ | 172 | raw_spin_unlock_irq(&pci_lock); \ |
173 | return ret; \ | 173 | return ret; \ |
174 | } | 174 | } |
175 | 175 | ||
@@ -220,8 +220,13 @@ static int pci_vpd_pci22_wait(struct pci_dev *dev) | |||
220 | return 0; | 220 | return 0; |
221 | } | 221 | } |
222 | 222 | ||
223 | if (time_after(jiffies, timeout)) | 223 | if (time_after(jiffies, timeout)) { |
224 | dev_printk(KERN_DEBUG, &dev->dev, | ||
225 | "vpd r/w failed. This is likely a firmware " | ||
226 | "bug on this device. Contact the card " | ||
227 | "vendor for a firmware update."); | ||
224 | return -ETIMEDOUT; | 228 | return -ETIMEDOUT; |
229 | } | ||
225 | if (fatal_signal_pending(current)) | 230 | if (fatal_signal_pending(current)) |
226 | return -EINTR; | 231 | return -EINTR; |
227 | if (!cond_resched()) | 232 | if (!cond_resched()) |
@@ -396,10 +401,10 @@ void pci_block_user_cfg_access(struct pci_dev *dev) | |||
396 | unsigned long flags; | 401 | unsigned long flags; |
397 | int was_blocked; | 402 | int was_blocked; |
398 | 403 | ||
399 | spin_lock_irqsave(&pci_lock, flags); | 404 | raw_spin_lock_irqsave(&pci_lock, flags); |
400 | was_blocked = dev->block_ucfg_access; | 405 | was_blocked = dev->block_ucfg_access; |
401 | dev->block_ucfg_access = 1; | 406 | dev->block_ucfg_access = 1; |
402 | spin_unlock_irqrestore(&pci_lock, flags); | 407 | raw_spin_unlock_irqrestore(&pci_lock, flags); |
403 | 408 | ||
404 | /* If we BUG() inside the pci_lock, we're guaranteed to hose | 409 | /* If we BUG() inside the pci_lock, we're guaranteed to hose |
405 | * the machine */ | 410 | * the machine */ |
@@ -417,7 +422,7 @@ void pci_unblock_user_cfg_access(struct pci_dev *dev) | |||
417 | { | 422 | { |
418 | unsigned long flags; | 423 | unsigned long flags; |
419 | 424 | ||
420 | spin_lock_irqsave(&pci_lock, flags); | 425 | raw_spin_lock_irqsave(&pci_lock, flags); |
421 | 426 | ||
422 | /* This indicates a problem in the caller, but we don't need | 427 | /* This indicates a problem in the caller, but we don't need |
423 | * to kill them, unlike a double-block above. */ | 428 | * to kill them, unlike a double-block above. */ |
@@ -425,6 +430,6 @@ void pci_unblock_user_cfg_access(struct pci_dev *dev) | |||
425 | 430 | ||
426 | dev->block_ucfg_access = 0; | 431 | dev->block_ucfg_access = 0; |
427 | wake_up_all(&pci_ucfg_wait); | 432 | wake_up_all(&pci_ucfg_wait); |
428 | spin_unlock_irqrestore(&pci_lock, flags); | 433 | raw_spin_unlock_irqrestore(&pci_lock, flags); |
429 | } | 434 | } |
430 | EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access); | 435 | EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access); |
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 33ead97f0c4b..0a19708074c2 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -131,9 +131,10 @@ static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, | |||
131 | if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || | 131 | if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || |
132 | scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) | 132 | scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) |
133 | (*cnt)++; | 133 | (*cnt)++; |
134 | else | 134 | else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) { |
135 | printk(KERN_WARNING PREFIX | 135 | printk(KERN_WARNING PREFIX |
136 | "Unsupported device scope\n"); | 136 | "Unsupported device scope\n"); |
137 | } | ||
137 | start += scope->length; | 138 | start += scope->length; |
138 | } | 139 | } |
139 | if (*cnt == 0) | 140 | if (*cnt == 0) |
@@ -309,6 +310,8 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev) | |||
309 | struct acpi_dmar_atsr *atsr; | 310 | struct acpi_dmar_atsr *atsr; |
310 | struct dmar_atsr_unit *atsru; | 311 | struct dmar_atsr_unit *atsru; |
311 | 312 | ||
313 | dev = pci_physfn(dev); | ||
314 | |||
312 | list_for_each_entry(atsru, &dmar_atsr_units, list) { | 315 | list_for_each_entry(atsru, &dmar_atsr_units, list) { |
313 | atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); | 316 | atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); |
314 | if (atsr->segment == pci_domain_nr(dev->bus)) | 317 | if (atsr->segment == pci_domain_nr(dev->bus)) |
@@ -358,12 +361,14 @@ dmar_parse_one_rhsa(struct acpi_dmar_header *header) | |||
358 | return 0; | 361 | return 0; |
359 | } | 362 | } |
360 | } | 363 | } |
361 | WARN(1, "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n" | 364 | WARN_TAINT( |
362 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | 365 | 1, TAINT_FIRMWARE_WORKAROUND, |
363 | drhd->reg_base_addr, | 366 | "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n" |
364 | dmi_get_system_info(DMI_BIOS_VENDOR), | 367 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", |
365 | dmi_get_system_info(DMI_BIOS_VERSION), | 368 | drhd->reg_base_addr, |
366 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | 369 | dmi_get_system_info(DMI_BIOS_VENDOR), |
370 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
371 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
367 | 372 | ||
368 | return 0; | 373 | return 0; |
369 | } | 374 | } |
@@ -507,7 +512,7 @@ parse_dmar_table(void) | |||
507 | return ret; | 512 | return ret; |
508 | } | 513 | } |
509 | 514 | ||
510 | int dmar_pci_device_match(struct pci_dev *devices[], int cnt, | 515 | static int dmar_pci_device_match(struct pci_dev *devices[], int cnt, |
511 | struct pci_dev *dev) | 516 | struct pci_dev *dev) |
512 | { | 517 | { |
513 | int index; | 518 | int index; |
@@ -530,6 +535,8 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev) | |||
530 | struct dmar_drhd_unit *dmaru = NULL; | 535 | struct dmar_drhd_unit *dmaru = NULL; |
531 | struct acpi_dmar_hardware_unit *drhd; | 536 | struct acpi_dmar_hardware_unit *drhd; |
532 | 537 | ||
538 | dev = pci_physfn(dev); | ||
539 | |||
533 | list_for_each_entry(dmaru, &dmar_drhd_units, list) { | 540 | list_for_each_entry(dmaru, &dmar_drhd_units, list) { |
534 | drhd = container_of(dmaru->hdr, | 541 | drhd = container_of(dmaru->hdr, |
535 | struct acpi_dmar_hardware_unit, | 542 | struct acpi_dmar_hardware_unit, |
@@ -614,7 +621,17 @@ int __init dmar_table_init(void) | |||
614 | return 0; | 621 | return 0; |
615 | } | 622 | } |
616 | 623 | ||
617 | static int bios_warned; | 624 | static void warn_invalid_dmar(u64 addr, const char *message) |
625 | { | ||
626 | WARN_TAINT_ONCE( | ||
627 | 1, TAINT_FIRMWARE_WORKAROUND, | ||
628 | "Your BIOS is broken; DMAR reported at address %llx%s!\n" | ||
629 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
630 | addr, message, | ||
631 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
632 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
633 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
634 | } | ||
618 | 635 | ||
619 | int __init check_zero_address(void) | 636 | int __init check_zero_address(void) |
620 | { | 637 | { |
@@ -640,13 +657,7 @@ int __init check_zero_address(void) | |||
640 | 657 | ||
641 | drhd = (void *)entry_header; | 658 | drhd = (void *)entry_header; |
642 | if (!drhd->address) { | 659 | if (!drhd->address) { |
643 | /* Promote an attitude of violence to a BIOS engineer today */ | 660 | warn_invalid_dmar(0, ""); |
644 | WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n" | ||
645 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
646 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
647 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
648 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
649 | bios_warned = 1; | ||
650 | goto failed; | 661 | goto failed; |
651 | } | 662 | } |
652 | 663 | ||
@@ -659,14 +670,8 @@ int __init check_zero_address(void) | |||
659 | ecap = dmar_readq(addr + DMAR_ECAP_REG); | 670 | ecap = dmar_readq(addr + DMAR_ECAP_REG); |
660 | early_iounmap(addr, VTD_PAGE_SIZE); | 671 | early_iounmap(addr, VTD_PAGE_SIZE); |
661 | if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) { | 672 | if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) { |
662 | /* Promote an attitude of violence to a BIOS engineer today */ | 673 | warn_invalid_dmar(drhd->address, |
663 | WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n" | 674 | " returns all ones"); |
664 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
665 | drhd->address, | ||
666 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
667 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
668 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
669 | bios_warned = 1; | ||
670 | goto failed; | 675 | goto failed; |
671 | } | 676 | } |
672 | } | 677 | } |
@@ -731,14 +736,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
731 | int msagaw = 0; | 736 | int msagaw = 0; |
732 | 737 | ||
733 | if (!drhd->reg_base_addr) { | 738 | if (!drhd->reg_base_addr) { |
734 | if (!bios_warned) { | 739 | warn_invalid_dmar(0, ""); |
735 | WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n" | ||
736 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
737 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
738 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
739 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
740 | bios_warned = 1; | ||
741 | } | ||
742 | return -EINVAL; | 740 | return -EINVAL; |
743 | } | 741 | } |
744 | 742 | ||
@@ -758,16 +756,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
758 | iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); | 756 | iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); |
759 | 757 | ||
760 | if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) { | 758 | if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) { |
761 | if (!bios_warned) { | 759 | warn_invalid_dmar(drhd->reg_base_addr, " returns all ones"); |
762 | /* Promote an attitude of violence to a BIOS engineer today */ | ||
763 | WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n" | ||
764 | "BIOS vendor: %s; Ver: %s; Product Version: %s\n", | ||
765 | drhd->reg_base_addr, | ||
766 | dmi_get_system_info(DMI_BIOS_VENDOR), | ||
767 | dmi_get_system_info(DMI_BIOS_VERSION), | ||
768 | dmi_get_system_info(DMI_PRODUCT_VERSION)); | ||
769 | bios_warned = 1; | ||
770 | } | ||
771 | goto err_unmap; | 760 | goto err_unmap; |
772 | } | 761 | } |
773 | 762 | ||
@@ -806,7 +795,8 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) | |||
806 | } | 795 | } |
807 | 796 | ||
808 | ver = readl(iommu->reg + DMAR_VER_REG); | 797 | ver = readl(iommu->reg + DMAR_VER_REG); |
809 | pr_info("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", | 798 | pr_info("IOMMU %d: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n", |
799 | iommu->seq_id, | ||
810 | (unsigned long long)drhd->reg_base_addr, | 800 | (unsigned long long)drhd->reg_base_addr, |
811 | DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), | 801 | DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), |
812 | (unsigned long long)iommu->cap, | 802 | (unsigned long long)iommu->cap, |
@@ -1457,9 +1447,11 @@ int dmar_reenable_qi(struct intel_iommu *iommu) | |||
1457 | /* | 1447 | /* |
1458 | * Check interrupt remapping support in DMAR table description. | 1448 | * Check interrupt remapping support in DMAR table description. |
1459 | */ | 1449 | */ |
1460 | int dmar_ir_support(void) | 1450 | int __init dmar_ir_support(void) |
1461 | { | 1451 | { |
1462 | struct acpi_table_dmar *dmar; | 1452 | struct acpi_table_dmar *dmar; |
1463 | dmar = (struct acpi_table_dmar *)dmar_tbl; | 1453 | dmar = (struct acpi_table_dmar *)dmar_tbl; |
1454 | if (!dmar) | ||
1455 | return 0; | ||
1464 | return dmar->flags & 0x1; | 1456 | return dmar->flags & 0x1; |
1465 | } | 1457 | } |
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 6ecbfb27db9d..e525263210ee 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c | |||
@@ -108,7 +108,7 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status); | |||
108 | static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status); | 108 | static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status); |
109 | static void ibm_handle_events(acpi_handle handle, u32 event, void *context); | 109 | static void ibm_handle_events(acpi_handle handle, u32 event, void *context); |
110 | static int ibm_get_table_from_acpi(char **bufp); | 110 | static int ibm_get_table_from_acpi(char **bufp); |
111 | static ssize_t ibm_read_apci_table(struct kobject *kobj, | 111 | static ssize_t ibm_read_apci_table(struct file *filp, struct kobject *kobj, |
112 | struct bin_attribute *bin_attr, | 112 | struct bin_attribute *bin_attr, |
113 | char *buffer, loff_t pos, size_t size); | 113 | char *buffer, loff_t pos, size_t size); |
114 | static acpi_status __init ibm_find_acpi_device(acpi_handle handle, | 114 | static acpi_status __init ibm_find_acpi_device(acpi_handle handle, |
@@ -351,6 +351,7 @@ read_table_done: | |||
351 | 351 | ||
352 | /** | 352 | /** |
353 | * ibm_read_apci_table - callback for the sysfs apci_table file | 353 | * ibm_read_apci_table - callback for the sysfs apci_table file |
354 | * @filp: the open sysfs file | ||
354 | * @kobj: the kobject this binary attribute is a part of | 355 | * @kobj: the kobject this binary attribute is a part of |
355 | * @bin_attr: struct bin_attribute for this file | 356 | * @bin_attr: struct bin_attribute for this file |
356 | * @buffer: the kernel space buffer to fill | 357 | * @buffer: the kernel space buffer to fill |
@@ -364,7 +365,7 @@ read_table_done: | |||
364 | * things get really tricky here... | 365 | * things get really tricky here... |
365 | * our solution is to only allow reading the table in all at once. | 366 | * our solution is to only allow reading the table in all at once. |
366 | */ | 367 | */ |
367 | static ssize_t ibm_read_apci_table(struct kobject *kobj, | 368 | static ssize_t ibm_read_apci_table(struct file *filp, struct kobject *kobj, |
368 | struct bin_attribute *bin_attr, | 369 | struct bin_attribute *bin_attr, |
369 | char *buffer, loff_t pos, size_t size) | 370 | char *buffer, loff_t pos, size_t size) |
370 | { | 371 | { |
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index f184d1d2ecbe..b3e5580c837b 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c | |||
@@ -848,7 +848,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
848 | goto err_disable_device; | 848 | goto err_disable_device; |
849 | } | 849 | } |
850 | 850 | ||
851 | /* Check for the proper subsytem ID's | 851 | /* Check for the proper subsystem ID's |
852 | * Intel uses a different SSID programming model than Compaq. | 852 | * Intel uses a different SSID programming model than Compaq. |
853 | * For Intel, each SSID bit identifies a PHP capability. | 853 | * For Intel, each SSID bit identifies a PHP capability. |
854 | * Also Intel HPC's may have RID=0. | 854 | * Also Intel HPC's may have RID=0. |
@@ -1075,13 +1075,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1075 | 1075 | ||
1076 | /* make our own copy of the pci bus structure, | 1076 | /* make our own copy of the pci bus structure, |
1077 | * as we like tweaking it a lot */ | 1077 | * as we like tweaking it a lot */ |
1078 | ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); | 1078 | ctrl->pci_bus = kmemdup(pdev->bus, sizeof(*ctrl->pci_bus), GFP_KERNEL); |
1079 | if (!ctrl->pci_bus) { | 1079 | if (!ctrl->pci_bus) { |
1080 | err("out of memory\n"); | 1080 | err("out of memory\n"); |
1081 | rc = -ENOMEM; | 1081 | rc = -ENOMEM; |
1082 | goto err_free_ctrl; | 1082 | goto err_free_ctrl; |
1083 | } | 1083 | } |
1084 | memcpy(ctrl->pci_bus, pdev->bus, sizeof(*ctrl->pci_bus)); | ||
1085 | 1084 | ||
1086 | ctrl->bus = pdev->bus->number; | 1085 | ctrl->bus = pdev->bus->number; |
1087 | ctrl->rev = pdev->revision; | 1086 | ctrl->rev = pdev->revision; |
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 0a16444c14c9..2fce726758d2 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
@@ -84,12 +84,6 @@ int pciehp_configure_device(struct slot *p_slot) | |||
84 | dev = pci_get_slot(parent, PCI_DEVFN(0, fn)); | 84 | dev = pci_get_slot(parent, PCI_DEVFN(0, fn)); |
85 | if (!dev) | 85 | if (!dev) |
86 | continue; | 86 | continue; |
87 | if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
88 | ctrl_err(ctrl, "Cannot hot-add display device %s\n", | ||
89 | pci_name(dev)); | ||
90 | pci_dev_put(dev); | ||
91 | continue; | ||
92 | } | ||
93 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || | 87 | if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || |
94 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { | 88 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { |
95 | pciehp_add_bridge(dev); | 89 | pciehp_add_bridge(dev); |
@@ -133,15 +127,9 @@ int pciehp_unconfigure_device(struct slot *p_slot) | |||
133 | presence = 0; | 127 | presence = 0; |
134 | 128 | ||
135 | for (j = 0; j < 8; j++) { | 129 | for (j = 0; j < 8; j++) { |
136 | struct pci_dev* temp = pci_get_slot(parent, PCI_DEVFN(0, j)); | 130 | struct pci_dev *temp = pci_get_slot(parent, PCI_DEVFN(0, j)); |
137 | if (!temp) | 131 | if (!temp) |
138 | continue; | 132 | continue; |
139 | if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) { | ||
140 | ctrl_err(ctrl, "Cannot remove display device %s\n", | ||
141 | pci_name(temp)); | ||
142 | pci_dev_put(temp); | ||
143 | continue; | ||
144 | } | ||
145 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) { | 133 | if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) { |
146 | pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); | 134 | pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); |
147 | if (bctl & PCI_BRIDGE_CTL_VGA) { | 135 | if (bctl & PCI_BRIDGE_CTL_VGA) { |
@@ -149,7 +137,8 @@ int pciehp_unconfigure_device(struct slot *p_slot) | |||
149 | "Cannot remove display device %s\n", | 137 | "Cannot remove display device %s\n", |
150 | pci_name(temp)); | 138 | pci_name(temp)); |
151 | pci_dev_put(temp); | 139 | pci_dev_put(temp); |
152 | continue; | 140 | rc = EINVAL; |
141 | break; | ||
153 | } | 142 | } |
154 | } | 143 | } |
155 | pci_remove_bus_device(temp); | 144 | pci_remove_bus_device(temp); |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 417312528ddf..796828fce34c 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -491,13 +491,11 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain) | |||
491 | 491 | ||
492 | domain->iommu_coherency = 1; | 492 | domain->iommu_coherency = 1; |
493 | 493 | ||
494 | i = find_first_bit(&domain->iommu_bmp, g_num_of_iommus); | 494 | for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) { |
495 | for (; i < g_num_of_iommus; ) { | ||
496 | if (!ecap_coherent(g_iommus[i]->ecap)) { | 495 | if (!ecap_coherent(g_iommus[i]->ecap)) { |
497 | domain->iommu_coherency = 0; | 496 | domain->iommu_coherency = 0; |
498 | break; | 497 | break; |
499 | } | 498 | } |
500 | i = find_next_bit(&domain->iommu_bmp, g_num_of_iommus, i+1); | ||
501 | } | 499 | } |
502 | } | 500 | } |
503 | 501 | ||
@@ -507,13 +505,11 @@ static void domain_update_iommu_snooping(struct dmar_domain *domain) | |||
507 | 505 | ||
508 | domain->iommu_snooping = 1; | 506 | domain->iommu_snooping = 1; |
509 | 507 | ||
510 | i = find_first_bit(&domain->iommu_bmp, g_num_of_iommus); | 508 | for_each_set_bit(i, &domain->iommu_bmp, g_num_of_iommus) { |
511 | for (; i < g_num_of_iommus; ) { | ||
512 | if (!ecap_sc_support(g_iommus[i]->ecap)) { | 509 | if (!ecap_sc_support(g_iommus[i]->ecap)) { |
513 | domain->iommu_snooping = 0; | 510 | domain->iommu_snooping = 0; |
514 | break; | 511 | break; |
515 | } | 512 | } |
516 | i = find_next_bit(&domain->iommu_bmp, g_num_of_iommus, i+1); | ||
517 | } | 513 | } |
518 | } | 514 | } |
519 | 515 | ||
@@ -1068,7 +1064,7 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain, | |||
1068 | } | 1064 | } |
1069 | 1065 | ||
1070 | static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | 1066 | static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, |
1071 | unsigned long pfn, unsigned int pages) | 1067 | unsigned long pfn, unsigned int pages, int map) |
1072 | { | 1068 | { |
1073 | unsigned int mask = ilog2(__roundup_pow_of_two(pages)); | 1069 | unsigned int mask = ilog2(__roundup_pow_of_two(pages)); |
1074 | uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT; | 1070 | uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT; |
@@ -1089,10 +1085,10 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, | |||
1089 | DMA_TLB_PSI_FLUSH); | 1085 | DMA_TLB_PSI_FLUSH); |
1090 | 1086 | ||
1091 | /* | 1087 | /* |
1092 | * In caching mode, domain ID 0 is reserved for non-present to present | 1088 | * In caching mode, changes of pages from non-present to present require |
1093 | * mapping flush. Device IOTLB doesn't need to be flushed in this case. | 1089 | * flush. However, device IOTLB doesn't need to be flushed in this case. |
1094 | */ | 1090 | */ |
1095 | if (!cap_caching_mode(iommu->cap) || did) | 1091 | if (!cap_caching_mode(iommu->cap) || !map) |
1096 | iommu_flush_dev_iotlb(iommu->domains[did], addr, mask); | 1092 | iommu_flush_dev_iotlb(iommu->domains[did], addr, mask); |
1097 | } | 1093 | } |
1098 | 1094 | ||
@@ -1154,7 +1150,8 @@ static int iommu_init_domains(struct intel_iommu *iommu) | |||
1154 | unsigned long nlongs; | 1150 | unsigned long nlongs; |
1155 | 1151 | ||
1156 | ndomains = cap_ndoms(iommu->cap); | 1152 | ndomains = cap_ndoms(iommu->cap); |
1157 | pr_debug("Number of Domains supportd <%ld>\n", ndomains); | 1153 | pr_debug("IOMMU %d: Number of Domains supportd <%ld>\n", iommu->seq_id, |
1154 | ndomains); | ||
1158 | nlongs = BITS_TO_LONGS(ndomains); | 1155 | nlongs = BITS_TO_LONGS(ndomains); |
1159 | 1156 | ||
1160 | spin_lock_init(&iommu->lock); | 1157 | spin_lock_init(&iommu->lock); |
@@ -1194,8 +1191,7 @@ void free_dmar_iommu(struct intel_iommu *iommu) | |||
1194 | unsigned long flags; | 1191 | unsigned long flags; |
1195 | 1192 | ||
1196 | if ((iommu->domains) && (iommu->domain_ids)) { | 1193 | if ((iommu->domains) && (iommu->domain_ids)) { |
1197 | i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap)); | 1194 | for_each_set_bit(i, iommu->domain_ids, cap_ndoms(iommu->cap)) { |
1198 | for (; i < cap_ndoms(iommu->cap); ) { | ||
1199 | domain = iommu->domains[i]; | 1195 | domain = iommu->domains[i]; |
1200 | clear_bit(i, iommu->domain_ids); | 1196 | clear_bit(i, iommu->domain_ids); |
1201 | 1197 | ||
@@ -1207,9 +1203,6 @@ void free_dmar_iommu(struct intel_iommu *iommu) | |||
1207 | domain_exit(domain); | 1203 | domain_exit(domain); |
1208 | } | 1204 | } |
1209 | spin_unlock_irqrestore(&domain->iommu_lock, flags); | 1205 | spin_unlock_irqrestore(&domain->iommu_lock, flags); |
1210 | |||
1211 | i = find_next_bit(iommu->domain_ids, | ||
1212 | cap_ndoms(iommu->cap), i+1); | ||
1213 | } | 1206 | } |
1214 | } | 1207 | } |
1215 | 1208 | ||
@@ -1292,14 +1285,11 @@ static void iommu_detach_domain(struct dmar_domain *domain, | |||
1292 | 1285 | ||
1293 | spin_lock_irqsave(&iommu->lock, flags); | 1286 | spin_lock_irqsave(&iommu->lock, flags); |
1294 | ndomains = cap_ndoms(iommu->cap); | 1287 | ndomains = cap_ndoms(iommu->cap); |
1295 | num = find_first_bit(iommu->domain_ids, ndomains); | 1288 | for_each_set_bit(num, iommu->domain_ids, ndomains) { |
1296 | for (; num < ndomains; ) { | ||
1297 | if (iommu->domains[num] == domain) { | 1289 | if (iommu->domains[num] == domain) { |
1298 | found = 1; | 1290 | found = 1; |
1299 | break; | 1291 | break; |
1300 | } | 1292 | } |
1301 | num = find_next_bit(iommu->domain_ids, | ||
1302 | cap_ndoms(iommu->cap), num+1); | ||
1303 | } | 1293 | } |
1304 | 1294 | ||
1305 | if (found) { | 1295 | if (found) { |
@@ -1485,15 +1475,12 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment, | |||
1485 | 1475 | ||
1486 | /* find an available domain id for this device in iommu */ | 1476 | /* find an available domain id for this device in iommu */ |
1487 | ndomains = cap_ndoms(iommu->cap); | 1477 | ndomains = cap_ndoms(iommu->cap); |
1488 | num = find_first_bit(iommu->domain_ids, ndomains); | 1478 | for_each_set_bit(num, iommu->domain_ids, ndomains) { |
1489 | for (; num < ndomains; ) { | ||
1490 | if (iommu->domains[num] == domain) { | 1479 | if (iommu->domains[num] == domain) { |
1491 | id = num; | 1480 | id = num; |
1492 | found = 1; | 1481 | found = 1; |
1493 | break; | 1482 | break; |
1494 | } | 1483 | } |
1495 | num = find_next_bit(iommu->domain_ids, | ||
1496 | cap_ndoms(iommu->cap), num+1); | ||
1497 | } | 1484 | } |
1498 | 1485 | ||
1499 | if (found == 0) { | 1486 | if (found == 0) { |
@@ -1558,7 +1545,7 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment, | |||
1558 | (((u16)bus) << 8) | devfn, | 1545 | (((u16)bus) << 8) | devfn, |
1559 | DMA_CCMD_MASK_NOBIT, | 1546 | DMA_CCMD_MASK_NOBIT, |
1560 | DMA_CCMD_DEVICE_INVL); | 1547 | DMA_CCMD_DEVICE_INVL); |
1561 | iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_DSI_FLUSH); | 1548 | iommu->flush.flush_iotlb(iommu, domain->id, 0, 0, DMA_TLB_DSI_FLUSH); |
1562 | } else { | 1549 | } else { |
1563 | iommu_flush_write_buffer(iommu); | 1550 | iommu_flush_write_buffer(iommu); |
1564 | } | 1551 | } |
@@ -2333,14 +2320,16 @@ int __init init_dmars(void) | |||
2333 | */ | 2320 | */ |
2334 | iommu->flush.flush_context = __iommu_flush_context; | 2321 | iommu->flush.flush_context = __iommu_flush_context; |
2335 | iommu->flush.flush_iotlb = __iommu_flush_iotlb; | 2322 | iommu->flush.flush_iotlb = __iommu_flush_iotlb; |
2336 | printk(KERN_INFO "IOMMU 0x%Lx: using Register based " | 2323 | printk(KERN_INFO "IOMMU %d 0x%Lx: using Register based " |
2337 | "invalidation\n", | 2324 | "invalidation\n", |
2325 | iommu->seq_id, | ||
2338 | (unsigned long long)drhd->reg_base_addr); | 2326 | (unsigned long long)drhd->reg_base_addr); |
2339 | } else { | 2327 | } else { |
2340 | iommu->flush.flush_context = qi_flush_context; | 2328 | iommu->flush.flush_context = qi_flush_context; |
2341 | iommu->flush.flush_iotlb = qi_flush_iotlb; | 2329 | iommu->flush.flush_iotlb = qi_flush_iotlb; |
2342 | printk(KERN_INFO "IOMMU 0x%Lx: using Queued " | 2330 | printk(KERN_INFO "IOMMU %d 0x%Lx: using Queued " |
2343 | "invalidation\n", | 2331 | "invalidation\n", |
2332 | iommu->seq_id, | ||
2344 | (unsigned long long)drhd->reg_base_addr); | 2333 | (unsigned long long)drhd->reg_base_addr); |
2345 | } | 2334 | } |
2346 | } | 2335 | } |
@@ -2621,7 +2610,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr, | |||
2621 | 2610 | ||
2622 | /* it's a non-present to present mapping. Only flush if caching mode */ | 2611 | /* it's a non-present to present mapping. Only flush if caching mode */ |
2623 | if (cap_caching_mode(iommu->cap)) | 2612 | if (cap_caching_mode(iommu->cap)) |
2624 | iommu_flush_iotlb_psi(iommu, 0, mm_to_dma_pfn(iova->pfn_lo), size); | 2613 | iommu_flush_iotlb_psi(iommu, domain->id, mm_to_dma_pfn(iova->pfn_lo), size, 1); |
2625 | else | 2614 | else |
2626 | iommu_flush_write_buffer(iommu); | 2615 | iommu_flush_write_buffer(iommu); |
2627 | 2616 | ||
@@ -2661,15 +2650,24 @@ static void flush_unmaps(void) | |||
2661 | if (!deferred_flush[i].next) | 2650 | if (!deferred_flush[i].next) |
2662 | continue; | 2651 | continue; |
2663 | 2652 | ||
2664 | iommu->flush.flush_iotlb(iommu, 0, 0, 0, | 2653 | /* In caching mode, global flushes turn emulation expensive */ |
2654 | if (!cap_caching_mode(iommu->cap)) | ||
2655 | iommu->flush.flush_iotlb(iommu, 0, 0, 0, | ||
2665 | DMA_TLB_GLOBAL_FLUSH); | 2656 | DMA_TLB_GLOBAL_FLUSH); |
2666 | for (j = 0; j < deferred_flush[i].next; j++) { | 2657 | for (j = 0; j < deferred_flush[i].next; j++) { |
2667 | unsigned long mask; | 2658 | unsigned long mask; |
2668 | struct iova *iova = deferred_flush[i].iova[j]; | 2659 | struct iova *iova = deferred_flush[i].iova[j]; |
2669 | 2660 | struct dmar_domain *domain = deferred_flush[i].domain[j]; | |
2670 | mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1)); | 2661 | |
2671 | iommu_flush_dev_iotlb(deferred_flush[i].domain[j], | 2662 | /* On real hardware multiple invalidations are expensive */ |
2672 | (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask); | 2663 | if (cap_caching_mode(iommu->cap)) |
2664 | iommu_flush_iotlb_psi(iommu, domain->id, | ||
2665 | iova->pfn_lo, iova->pfn_hi - iova->pfn_lo + 1, 0); | ||
2666 | else { | ||
2667 | mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1)); | ||
2668 | iommu_flush_dev_iotlb(deferred_flush[i].domain[j], | ||
2669 | (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask); | ||
2670 | } | ||
2673 | __free_iova(&deferred_flush[i].domain[j]->iovad, iova); | 2671 | __free_iova(&deferred_flush[i].domain[j]->iovad, iova); |
2674 | } | 2672 | } |
2675 | deferred_flush[i].next = 0; | 2673 | deferred_flush[i].next = 0; |
@@ -2750,7 +2748,7 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, | |||
2750 | 2748 | ||
2751 | if (intel_iommu_strict) { | 2749 | if (intel_iommu_strict) { |
2752 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, | 2750 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, |
2753 | last_pfn - start_pfn + 1); | 2751 | last_pfn - start_pfn + 1, 0); |
2754 | /* free iova */ | 2752 | /* free iova */ |
2755 | __free_iova(&domain->iovad, iova); | 2753 | __free_iova(&domain->iovad, iova); |
2756 | } else { | 2754 | } else { |
@@ -2840,7 +2838,7 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, | |||
2840 | 2838 | ||
2841 | if (intel_iommu_strict) { | 2839 | if (intel_iommu_strict) { |
2842 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, | 2840 | iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, |
2843 | last_pfn - start_pfn + 1); | 2841 | last_pfn - start_pfn + 1, 0); |
2844 | /* free iova */ | 2842 | /* free iova */ |
2845 | __free_iova(&domain->iovad, iova); | 2843 | __free_iova(&domain->iovad, iova); |
2846 | } else { | 2844 | } else { |
@@ -2874,7 +2872,6 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne | |||
2874 | struct dmar_domain *domain; | 2872 | struct dmar_domain *domain; |
2875 | size_t size = 0; | 2873 | size_t size = 0; |
2876 | int prot = 0; | 2874 | int prot = 0; |
2877 | size_t offset_pfn = 0; | ||
2878 | struct iova *iova = NULL; | 2875 | struct iova *iova = NULL; |
2879 | int ret; | 2876 | int ret; |
2880 | struct scatterlist *sg; | 2877 | struct scatterlist *sg; |
@@ -2928,7 +2925,7 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne | |||
2928 | 2925 | ||
2929 | /* it's a non-present to present mapping. Only flush if caching mode */ | 2926 | /* it's a non-present to present mapping. Only flush if caching mode */ |
2930 | if (cap_caching_mode(iommu->cap)) | 2927 | if (cap_caching_mode(iommu->cap)) |
2931 | iommu_flush_iotlb_psi(iommu, 0, start_vpfn, offset_pfn); | 2928 | iommu_flush_iotlb_psi(iommu, domain->id, start_vpfn, size, 1); |
2932 | else | 2929 | else |
2933 | iommu_flush_write_buffer(iommu); | 2930 | iommu_flush_write_buffer(iommu); |
2934 | 2931 | ||
@@ -3436,22 +3433,6 @@ static void vm_domain_remove_all_dev_info(struct dmar_domain *domain) | |||
3436 | /* domain id for virtual machine, it won't be set in context */ | 3433 | /* domain id for virtual machine, it won't be set in context */ |
3437 | static unsigned long vm_domid; | 3434 | static unsigned long vm_domid; |
3438 | 3435 | ||
3439 | static int vm_domain_min_agaw(struct dmar_domain *domain) | ||
3440 | { | ||
3441 | int i; | ||
3442 | int min_agaw = domain->agaw; | ||
3443 | |||
3444 | i = find_first_bit(&domain->iommu_bmp, g_num_of_iommus); | ||
3445 | for (; i < g_num_of_iommus; ) { | ||
3446 | if (min_agaw > g_iommus[i]->agaw) | ||
3447 | min_agaw = g_iommus[i]->agaw; | ||
3448 | |||
3449 | i = find_next_bit(&domain->iommu_bmp, g_num_of_iommus, i+1); | ||
3450 | } | ||
3451 | |||
3452 | return min_agaw; | ||
3453 | } | ||
3454 | |||
3455 | static struct dmar_domain *iommu_alloc_vm_domain(void) | 3436 | static struct dmar_domain *iommu_alloc_vm_domain(void) |
3456 | { | 3437 | { |
3457 | struct dmar_domain *domain; | 3438 | struct dmar_domain *domain; |
@@ -3512,8 +3493,7 @@ static void iommu_free_vm_domain(struct dmar_domain *domain) | |||
3512 | iommu = drhd->iommu; | 3493 | iommu = drhd->iommu; |
3513 | 3494 | ||
3514 | ndomains = cap_ndoms(iommu->cap); | 3495 | ndomains = cap_ndoms(iommu->cap); |
3515 | i = find_first_bit(iommu->domain_ids, ndomains); | 3496 | for_each_set_bit(i, iommu->domain_ids, ndomains) { |
3516 | for (; i < ndomains; ) { | ||
3517 | if (iommu->domains[i] == domain) { | 3497 | if (iommu->domains[i] == domain) { |
3518 | spin_lock_irqsave(&iommu->lock, flags); | 3498 | spin_lock_irqsave(&iommu->lock, flags); |
3519 | clear_bit(i, iommu->domain_ids); | 3499 | clear_bit(i, iommu->domain_ids); |
@@ -3521,7 +3501,6 @@ static void iommu_free_vm_domain(struct dmar_domain *domain) | |||
3521 | spin_unlock_irqrestore(&iommu->lock, flags); | 3501 | spin_unlock_irqrestore(&iommu->lock, flags); |
3522 | break; | 3502 | break; |
3523 | } | 3503 | } |
3524 | i = find_next_bit(iommu->domain_ids, ndomains, i+1); | ||
3525 | } | 3504 | } |
3526 | } | 3505 | } |
3527 | } | 3506 | } |
@@ -3582,7 +3561,6 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, | |||
3582 | struct pci_dev *pdev = to_pci_dev(dev); | 3561 | struct pci_dev *pdev = to_pci_dev(dev); |
3583 | struct intel_iommu *iommu; | 3562 | struct intel_iommu *iommu; |
3584 | int addr_width; | 3563 | int addr_width; |
3585 | u64 end; | ||
3586 | 3564 | ||
3587 | /* normally pdev is not mapped */ | 3565 | /* normally pdev is not mapped */ |
3588 | if (unlikely(domain_context_mapped(pdev))) { | 3566 | if (unlikely(domain_context_mapped(pdev))) { |
@@ -3605,14 +3583,30 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, | |||
3605 | 3583 | ||
3606 | /* check if this iommu agaw is sufficient for max mapped address */ | 3584 | /* check if this iommu agaw is sufficient for max mapped address */ |
3607 | addr_width = agaw_to_width(iommu->agaw); | 3585 | addr_width = agaw_to_width(iommu->agaw); |
3608 | end = DOMAIN_MAX_ADDR(addr_width); | 3586 | if (addr_width > cap_mgaw(iommu->cap)) |
3609 | end = end & VTD_PAGE_MASK; | 3587 | addr_width = cap_mgaw(iommu->cap); |
3610 | if (end < dmar_domain->max_addr) { | 3588 | |
3611 | printk(KERN_ERR "%s: iommu agaw (%d) is not " | 3589 | if (dmar_domain->max_addr > (1LL << addr_width)) { |
3590 | printk(KERN_ERR "%s: iommu width (%d) is not " | ||
3612 | "sufficient for the mapped address (%llx)\n", | 3591 | "sufficient for the mapped address (%llx)\n", |
3613 | __func__, iommu->agaw, dmar_domain->max_addr); | 3592 | __func__, addr_width, dmar_domain->max_addr); |
3614 | return -EFAULT; | 3593 | return -EFAULT; |
3615 | } | 3594 | } |
3595 | dmar_domain->gaw = addr_width; | ||
3596 | |||
3597 | /* | ||
3598 | * Knock out extra levels of page tables if necessary | ||
3599 | */ | ||
3600 | while (iommu->agaw < dmar_domain->agaw) { | ||
3601 | struct dma_pte *pte; | ||
3602 | |||
3603 | pte = dmar_domain->pgd; | ||
3604 | if (dma_pte_present(pte)) { | ||
3605 | free_pgtable_page(dmar_domain->pgd); | ||
3606 | dmar_domain->pgd = (struct dma_pte *)dma_pte_addr(pte); | ||
3607 | } | ||
3608 | dmar_domain->agaw--; | ||
3609 | } | ||
3616 | 3610 | ||
3617 | return domain_add_dev_info(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL); | 3611 | return domain_add_dev_info(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL); |
3618 | } | 3612 | } |
@@ -3626,14 +3620,14 @@ static void intel_iommu_detach_device(struct iommu_domain *domain, | |||
3626 | domain_remove_one_dev_info(dmar_domain, pdev); | 3620 | domain_remove_one_dev_info(dmar_domain, pdev); |
3627 | } | 3621 | } |
3628 | 3622 | ||
3629 | static int intel_iommu_map_range(struct iommu_domain *domain, | 3623 | static int intel_iommu_map(struct iommu_domain *domain, |
3630 | unsigned long iova, phys_addr_t hpa, | 3624 | unsigned long iova, phys_addr_t hpa, |
3631 | size_t size, int iommu_prot) | 3625 | int gfp_order, int iommu_prot) |
3632 | { | 3626 | { |
3633 | struct dmar_domain *dmar_domain = domain->priv; | 3627 | struct dmar_domain *dmar_domain = domain->priv; |
3634 | u64 max_addr; | 3628 | u64 max_addr; |
3635 | int addr_width; | ||
3636 | int prot = 0; | 3629 | int prot = 0; |
3630 | size_t size; | ||
3637 | int ret; | 3631 | int ret; |
3638 | 3632 | ||
3639 | if (iommu_prot & IOMMU_READ) | 3633 | if (iommu_prot & IOMMU_READ) |
@@ -3643,20 +3637,17 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
3643 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) | 3637 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) |
3644 | prot |= DMA_PTE_SNP; | 3638 | prot |= DMA_PTE_SNP; |
3645 | 3639 | ||
3640 | size = PAGE_SIZE << gfp_order; | ||
3646 | max_addr = iova + size; | 3641 | max_addr = iova + size; |
3647 | if (dmar_domain->max_addr < max_addr) { | 3642 | if (dmar_domain->max_addr < max_addr) { |
3648 | int min_agaw; | ||
3649 | u64 end; | 3643 | u64 end; |
3650 | 3644 | ||
3651 | /* check if minimum agaw is sufficient for mapped address */ | 3645 | /* check if minimum agaw is sufficient for mapped address */ |
3652 | min_agaw = vm_domain_min_agaw(dmar_domain); | 3646 | end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1; |
3653 | addr_width = agaw_to_width(min_agaw); | ||
3654 | end = DOMAIN_MAX_ADDR(addr_width); | ||
3655 | end = end & VTD_PAGE_MASK; | ||
3656 | if (end < max_addr) { | 3647 | if (end < max_addr) { |
3657 | printk(KERN_ERR "%s: iommu agaw (%d) is not " | 3648 | printk(KERN_ERR "%s: iommu width (%d) is not " |
3658 | "sufficient for the mapped address (%llx)\n", | 3649 | "sufficient for the mapped address (%llx)\n", |
3659 | __func__, min_agaw, max_addr); | 3650 | __func__, dmar_domain->gaw, max_addr); |
3660 | return -EFAULT; | 3651 | return -EFAULT; |
3661 | } | 3652 | } |
3662 | dmar_domain->max_addr = max_addr; | 3653 | dmar_domain->max_addr = max_addr; |
@@ -3669,19 +3660,19 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
3669 | return ret; | 3660 | return ret; |
3670 | } | 3661 | } |
3671 | 3662 | ||
3672 | static void intel_iommu_unmap_range(struct iommu_domain *domain, | 3663 | static int intel_iommu_unmap(struct iommu_domain *domain, |
3673 | unsigned long iova, size_t size) | 3664 | unsigned long iova, int gfp_order) |
3674 | { | 3665 | { |
3675 | struct dmar_domain *dmar_domain = domain->priv; | 3666 | struct dmar_domain *dmar_domain = domain->priv; |
3676 | 3667 | size_t size = PAGE_SIZE << gfp_order; | |
3677 | if (!size) | ||
3678 | return; | ||
3679 | 3668 | ||
3680 | dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, | 3669 | dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, |
3681 | (iova + size - 1) >> VTD_PAGE_SHIFT); | 3670 | (iova + size - 1) >> VTD_PAGE_SHIFT); |
3682 | 3671 | ||
3683 | if (dmar_domain->max_addr == iova + size) | 3672 | if (dmar_domain->max_addr == iova + size) |
3684 | dmar_domain->max_addr = iova; | 3673 | dmar_domain->max_addr = iova; |
3674 | |||
3675 | return gfp_order; | ||
3685 | } | 3676 | } |
3686 | 3677 | ||
3687 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, | 3678 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, |
@@ -3714,8 +3705,8 @@ static struct iommu_ops intel_iommu_ops = { | |||
3714 | .domain_destroy = intel_iommu_domain_destroy, | 3705 | .domain_destroy = intel_iommu_domain_destroy, |
3715 | .attach_dev = intel_iommu_attach_device, | 3706 | .attach_dev = intel_iommu_attach_device, |
3716 | .detach_dev = intel_iommu_detach_device, | 3707 | .detach_dev = intel_iommu_detach_device, |
3717 | .map = intel_iommu_map_range, | 3708 | .map = intel_iommu_map, |
3718 | .unmap = intel_iommu_unmap_range, | 3709 | .unmap = intel_iommu_unmap, |
3719 | .iova_to_phys = intel_iommu_iova_to_phys, | 3710 | .iova_to_phys = intel_iommu_iova_to_phys, |
3720 | .domain_has_cap = intel_iommu_domain_has_cap, | 3711 | .domain_has_cap = intel_iommu_domain_has_cap, |
3721 | }; | 3712 | }; |
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index 6ee98a56946f..1315ac688aa2 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
@@ -832,9 +832,9 @@ static int ir_parse_ioapic_hpet_scope(struct acpi_dmar_header *header, | |||
832 | return -1; | 832 | return -1; |
833 | } | 833 | } |
834 | 834 | ||
835 | printk(KERN_INFO "IOAPIC id %d under DRHD base" | 835 | printk(KERN_INFO "IOAPIC id %d under DRHD base " |
836 | " 0x%Lx\n", scope->enumeration_id, | 836 | " 0x%Lx IOMMU %d\n", scope->enumeration_id, |
837 | drhd->address); | 837 | drhd->address, iommu->seq_id); |
838 | 838 | ||
839 | ir_parse_one_ioapic_scope(scope, iommu); | 839 | ir_parse_one_ioapic_scope(scope, iommu); |
840 | } else if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_HPET) { | 840 | } else if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_HPET) { |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index fad93983bfed..afd2fbf7d797 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/stat.h> | 21 | #include <linux/stat.h> |
22 | #include <linux/topology.h> | 22 | #include <linux/topology.h> |
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/fs.h> | ||
24 | #include <linux/capability.h> | 25 | #include <linux/capability.h> |
25 | #include <linux/pci-aspm.h> | 26 | #include <linux/pci-aspm.h> |
26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
@@ -357,7 +358,8 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
357 | struct device_attribute vga_attr = __ATTR_RO(boot_vga); | 358 | struct device_attribute vga_attr = __ATTR_RO(boot_vga); |
358 | 359 | ||
359 | static ssize_t | 360 | static ssize_t |
360 | pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, | 361 | pci_read_config(struct file *filp, struct kobject *kobj, |
362 | struct bin_attribute *bin_attr, | ||
361 | char *buf, loff_t off, size_t count) | 363 | char *buf, loff_t off, size_t count) |
362 | { | 364 | { |
363 | struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); | 365 | struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); |
@@ -366,7 +368,7 @@ pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
366 | u8 *data = (u8*) buf; | 368 | u8 *data = (u8*) buf; |
367 | 369 | ||
368 | /* Several chips lock up trying to read undefined config space */ | 370 | /* Several chips lock up trying to read undefined config space */ |
369 | if (capable(CAP_SYS_ADMIN)) { | 371 | if (cap_raised(filp->f_cred->cap_effective, CAP_SYS_ADMIN)) { |
370 | size = dev->cfg_size; | 372 | size = dev->cfg_size; |
371 | } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { | 373 | } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { |
372 | size = 128; | 374 | size = 128; |
@@ -430,7 +432,8 @@ pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
430 | } | 432 | } |
431 | 433 | ||
432 | static ssize_t | 434 | static ssize_t |
433 | pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr, | 435 | pci_write_config(struct file* filp, struct kobject *kobj, |
436 | struct bin_attribute *bin_attr, | ||
434 | char *buf, loff_t off, size_t count) | 437 | char *buf, loff_t off, size_t count) |
435 | { | 438 | { |
436 | struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); | 439 | struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); |
@@ -487,7 +490,8 @@ pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
487 | } | 490 | } |
488 | 491 | ||
489 | static ssize_t | 492 | static ssize_t |
490 | read_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr, | 493 | read_vpd_attr(struct file *filp, struct kobject *kobj, |
494 | struct bin_attribute *bin_attr, | ||
491 | char *buf, loff_t off, size_t count) | 495 | char *buf, loff_t off, size_t count) |
492 | { | 496 | { |
493 | struct pci_dev *dev = | 497 | struct pci_dev *dev = |
@@ -502,7 +506,8 @@ read_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
502 | } | 506 | } |
503 | 507 | ||
504 | static ssize_t | 508 | static ssize_t |
505 | write_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr, | 509 | write_vpd_attr(struct file *filp, struct kobject *kobj, |
510 | struct bin_attribute *bin_attr, | ||
506 | char *buf, loff_t off, size_t count) | 511 | char *buf, loff_t off, size_t count) |
507 | { | 512 | { |
508 | struct pci_dev *dev = | 513 | struct pci_dev *dev = |
@@ -519,6 +524,7 @@ write_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
519 | #ifdef HAVE_PCI_LEGACY | 524 | #ifdef HAVE_PCI_LEGACY |
520 | /** | 525 | /** |
521 | * pci_read_legacy_io - read byte(s) from legacy I/O port space | 526 | * pci_read_legacy_io - read byte(s) from legacy I/O port space |
527 | * @filp: open sysfs file | ||
522 | * @kobj: kobject corresponding to file to read from | 528 | * @kobj: kobject corresponding to file to read from |
523 | * @bin_attr: struct bin_attribute for this file | 529 | * @bin_attr: struct bin_attribute for this file |
524 | * @buf: buffer to store results | 530 | * @buf: buffer to store results |
@@ -529,7 +535,8 @@ write_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
529 | * callback routine (pci_legacy_read). | 535 | * callback routine (pci_legacy_read). |
530 | */ | 536 | */ |
531 | static ssize_t | 537 | static ssize_t |
532 | pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, | 538 | pci_read_legacy_io(struct file *filp, struct kobject *kobj, |
539 | struct bin_attribute *bin_attr, | ||
533 | char *buf, loff_t off, size_t count) | 540 | char *buf, loff_t off, size_t count) |
534 | { | 541 | { |
535 | struct pci_bus *bus = to_pci_bus(container_of(kobj, | 542 | struct pci_bus *bus = to_pci_bus(container_of(kobj, |
@@ -545,6 +552,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
545 | 552 | ||
546 | /** | 553 | /** |
547 | * pci_write_legacy_io - write byte(s) to legacy I/O port space | 554 | * pci_write_legacy_io - write byte(s) to legacy I/O port space |
555 | * @filp: open sysfs file | ||
548 | * @kobj: kobject corresponding to file to read from | 556 | * @kobj: kobject corresponding to file to read from |
549 | * @bin_attr: struct bin_attribute for this file | 557 | * @bin_attr: struct bin_attribute for this file |
550 | * @buf: buffer containing value to be written | 558 | * @buf: buffer containing value to be written |
@@ -555,7 +563,8 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
555 | * callback routine (pci_legacy_write). | 563 | * callback routine (pci_legacy_write). |
556 | */ | 564 | */ |
557 | static ssize_t | 565 | static ssize_t |
558 | pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, | 566 | pci_write_legacy_io(struct file *filp, struct kobject *kobj, |
567 | struct bin_attribute *bin_attr, | ||
559 | char *buf, loff_t off, size_t count) | 568 | char *buf, loff_t off, size_t count) |
560 | { | 569 | { |
561 | struct pci_bus *bus = to_pci_bus(container_of(kobj, | 570 | struct pci_bus *bus = to_pci_bus(container_of(kobj, |
@@ -570,6 +579,7 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
570 | 579 | ||
571 | /** | 580 | /** |
572 | * pci_mmap_legacy_mem - map legacy PCI memory into user memory space | 581 | * pci_mmap_legacy_mem - map legacy PCI memory into user memory space |
582 | * @filp: open sysfs file | ||
573 | * @kobj: kobject corresponding to device to be mapped | 583 | * @kobj: kobject corresponding to device to be mapped |
574 | * @attr: struct bin_attribute for this file | 584 | * @attr: struct bin_attribute for this file |
575 | * @vma: struct vm_area_struct passed to mmap | 585 | * @vma: struct vm_area_struct passed to mmap |
@@ -579,7 +589,8 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
579 | * memory space. | 589 | * memory space. |
580 | */ | 590 | */ |
581 | static int | 591 | static int |
582 | pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr, | 592 | pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj, |
593 | struct bin_attribute *attr, | ||
583 | struct vm_area_struct *vma) | 594 | struct vm_area_struct *vma) |
584 | { | 595 | { |
585 | struct pci_bus *bus = to_pci_bus(container_of(kobj, | 596 | struct pci_bus *bus = to_pci_bus(container_of(kobj, |
@@ -591,6 +602,7 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr, | |||
591 | 602 | ||
592 | /** | 603 | /** |
593 | * pci_mmap_legacy_io - map legacy PCI IO into user memory space | 604 | * pci_mmap_legacy_io - map legacy PCI IO into user memory space |
605 | * @filp: open sysfs file | ||
594 | * @kobj: kobject corresponding to device to be mapped | 606 | * @kobj: kobject corresponding to device to be mapped |
595 | * @attr: struct bin_attribute for this file | 607 | * @attr: struct bin_attribute for this file |
596 | * @vma: struct vm_area_struct passed to mmap | 608 | * @vma: struct vm_area_struct passed to mmap |
@@ -600,7 +612,8 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr, | |||
600 | * memory space. Returns -ENOSYS if the operation isn't supported | 612 | * memory space. Returns -ENOSYS if the operation isn't supported |
601 | */ | 613 | */ |
602 | static int | 614 | static int |
603 | pci_mmap_legacy_io(struct kobject *kobj, struct bin_attribute *attr, | 615 | pci_mmap_legacy_io(struct file *filp, struct kobject *kobj, |
616 | struct bin_attribute *attr, | ||
604 | struct vm_area_struct *vma) | 617 | struct vm_area_struct *vma) |
605 | { | 618 | { |
606 | struct pci_bus *bus = to_pci_bus(container_of(kobj, | 619 | struct pci_bus *bus = to_pci_bus(container_of(kobj, |
@@ -750,14 +763,16 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, | |||
750 | } | 763 | } |
751 | 764 | ||
752 | static int | 765 | static int |
753 | pci_mmap_resource_uc(struct kobject *kobj, struct bin_attribute *attr, | 766 | pci_mmap_resource_uc(struct file *filp, struct kobject *kobj, |
767 | struct bin_attribute *attr, | ||
754 | struct vm_area_struct *vma) | 768 | struct vm_area_struct *vma) |
755 | { | 769 | { |
756 | return pci_mmap_resource(kobj, attr, vma, 0); | 770 | return pci_mmap_resource(kobj, attr, vma, 0); |
757 | } | 771 | } |
758 | 772 | ||
759 | static int | 773 | static int |
760 | pci_mmap_resource_wc(struct kobject *kobj, struct bin_attribute *attr, | 774 | pci_mmap_resource_wc(struct file *filp, struct kobject *kobj, |
775 | struct bin_attribute *attr, | ||
761 | struct vm_area_struct *vma) | 776 | struct vm_area_struct *vma) |
762 | { | 777 | { |
763 | return pci_mmap_resource(kobj, attr, vma, 1); | 778 | return pci_mmap_resource(kobj, attr, vma, 1); |
@@ -861,6 +876,7 @@ void __weak pci_remove_resource_files(struct pci_dev *dev) { return; } | |||
861 | 876 | ||
862 | /** | 877 | /** |
863 | * pci_write_rom - used to enable access to the PCI ROM display | 878 | * pci_write_rom - used to enable access to the PCI ROM display |
879 | * @filp: sysfs file | ||
864 | * @kobj: kernel object handle | 880 | * @kobj: kernel object handle |
865 | * @bin_attr: struct bin_attribute for this file | 881 | * @bin_attr: struct bin_attribute for this file |
866 | * @buf: user input | 882 | * @buf: user input |
@@ -870,7 +886,8 @@ void __weak pci_remove_resource_files(struct pci_dev *dev) { return; } | |||
870 | * writing anything except 0 enables it | 886 | * writing anything except 0 enables it |
871 | */ | 887 | */ |
872 | static ssize_t | 888 | static ssize_t |
873 | pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr, | 889 | pci_write_rom(struct file *filp, struct kobject *kobj, |
890 | struct bin_attribute *bin_attr, | ||
874 | char *buf, loff_t off, size_t count) | 891 | char *buf, loff_t off, size_t count) |
875 | { | 892 | { |
876 | struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); | 893 | struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); |
@@ -885,6 +902,7 @@ pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
885 | 902 | ||
886 | /** | 903 | /** |
887 | * pci_read_rom - read a PCI ROM | 904 | * pci_read_rom - read a PCI ROM |
905 | * @filp: sysfs file | ||
888 | * @kobj: kernel object handle | 906 | * @kobj: kernel object handle |
889 | * @bin_attr: struct bin_attribute for this file | 907 | * @bin_attr: struct bin_attribute for this file |
890 | * @buf: where to put the data we read from the ROM | 908 | * @buf: where to put the data we read from the ROM |
@@ -895,7 +913,8 @@ pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
895 | * device corresponding to @kobj. | 913 | * device corresponding to @kobj. |
896 | */ | 914 | */ |
897 | static ssize_t | 915 | static ssize_t |
898 | pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr, | 916 | pci_read_rom(struct file *filp, struct kobject *kobj, |
917 | struct bin_attribute *bin_attr, | ||
899 | char *buf, loff_t off, size_t count) | 918 | char *buf, loff_t off, size_t count) |
900 | { | 919 | { |
901 | struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); | 920 | struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); |
@@ -960,7 +979,12 @@ static ssize_t reset_store(struct device *dev, | |||
960 | 979 | ||
961 | if (val != 1) | 980 | if (val != 1) |
962 | return -EINVAL; | 981 | return -EINVAL; |
963 | return pci_reset_function(pdev); | 982 | |
983 | result = pci_reset_function(pdev); | ||
984 | if (result < 0) | ||
985 | return result; | ||
986 | |||
987 | return count; | ||
964 | } | 988 | } |
965 | 989 | ||
966 | static struct device_attribute reset_attr = __ATTR(reset, 0200, NULL, reset_store); | 990 | static struct device_attribute reset_attr = __ATTR(reset, 0200, NULL, reset_store); |
@@ -1011,6 +1035,39 @@ error: | |||
1011 | return retval; | 1035 | return retval; |
1012 | } | 1036 | } |
1013 | 1037 | ||
1038 | static void pci_remove_slot_links(struct pci_dev *dev) | ||
1039 | { | ||
1040 | char func[10]; | ||
1041 | struct pci_slot *slot; | ||
1042 | |||
1043 | sysfs_remove_link(&dev->dev.kobj, "slot"); | ||
1044 | list_for_each_entry(slot, &dev->bus->slots, list) { | ||
1045 | if (slot->number != PCI_SLOT(dev->devfn)) | ||
1046 | continue; | ||
1047 | snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn)); | ||
1048 | sysfs_remove_link(&slot->kobj, func); | ||
1049 | } | ||
1050 | } | ||
1051 | |||
1052 | static int pci_create_slot_links(struct pci_dev *dev) | ||
1053 | { | ||
1054 | int result = 0; | ||
1055 | char func[10]; | ||
1056 | struct pci_slot *slot; | ||
1057 | |||
1058 | list_for_each_entry(slot, &dev->bus->slots, list) { | ||
1059 | if (slot->number != PCI_SLOT(dev->devfn)) | ||
1060 | continue; | ||
1061 | result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot"); | ||
1062 | if (result) | ||
1063 | goto out; | ||
1064 | snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn)); | ||
1065 | result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func); | ||
1066 | } | ||
1067 | out: | ||
1068 | return result; | ||
1069 | } | ||
1070 | |||
1014 | int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | 1071 | int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) |
1015 | { | 1072 | { |
1016 | int retval; | 1073 | int retval; |
@@ -1073,6 +1130,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | |||
1073 | if (retval) | 1130 | if (retval) |
1074 | goto err_vga_file; | 1131 | goto err_vga_file; |
1075 | 1132 | ||
1133 | pci_create_slot_links(pdev); | ||
1134 | |||
1076 | return 0; | 1135 | return 0; |
1077 | 1136 | ||
1078 | err_vga_file: | 1137 | err_vga_file: |
@@ -1122,6 +1181,8 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev) | |||
1122 | if (!sysfs_initialized) | 1181 | if (!sysfs_initialized) |
1123 | return; | 1182 | return; |
1124 | 1183 | ||
1184 | pci_remove_slot_links(pdev); | ||
1185 | |||
1125 | pci_remove_capabilities_sysfs(pdev); | 1186 | pci_remove_capabilities_sysfs(pdev); |
1126 | 1187 | ||
1127 | if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE) | 1188 | if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE) |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 37499127c801..60f30e7f1c8c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -1193,7 +1193,7 @@ void pci_disable_enabled_device(struct pci_dev *dev) | |||
1193 | * anymore. This only involves disabling PCI bus-mastering, if active. | 1193 | * anymore. This only involves disabling PCI bus-mastering, if active. |
1194 | * | 1194 | * |
1195 | * Note we don't actually disable the device until all callers of | 1195 | * Note we don't actually disable the device until all callers of |
1196 | * pci_device_enable() have called pci_device_disable(). | 1196 | * pci_enable_device() have called pci_disable_device(). |
1197 | */ | 1197 | */ |
1198 | void | 1198 | void |
1199 | pci_disable_device(struct pci_dev *dev) | 1199 | pci_disable_device(struct pci_dev *dev) |
@@ -1503,7 +1503,7 @@ int pci_prepare_to_sleep(struct pci_dev *dev) | |||
1503 | * pci_back_from_sleep - turn PCI device on during system-wide transition into working state | 1503 | * pci_back_from_sleep - turn PCI device on during system-wide transition into working state |
1504 | * @dev: Device to handle. | 1504 | * @dev: Device to handle. |
1505 | * | 1505 | * |
1506 | * Disable device's sytem wake-up capability and put it into D0. | 1506 | * Disable device's system wake-up capability and put it into D0. |
1507 | */ | 1507 | */ |
1508 | int pci_back_from_sleep(struct pci_dev *dev) | 1508 | int pci_back_from_sleep(struct pci_dev *dev) |
1509 | { | 1509 | { |
@@ -1631,7 +1631,6 @@ void pci_pm_init(struct pci_dev *dev) | |||
1631 | * let the user space enable it to wake up the system as needed. | 1631 | * let the user space enable it to wake up the system as needed. |
1632 | */ | 1632 | */ |
1633 | device_set_wakeup_capable(&dev->dev, true); | 1633 | device_set_wakeup_capable(&dev->dev, true); |
1634 | device_set_wakeup_enable(&dev->dev, false); | ||
1635 | /* Disable the PME# generation functionality */ | 1634 | /* Disable the PME# generation functionality */ |
1636 | pci_pme_active(dev, false); | 1635 | pci_pme_active(dev, false); |
1637 | } else { | 1636 | } else { |
@@ -1655,7 +1654,6 @@ void platform_pci_wakeup_init(struct pci_dev *dev) | |||
1655 | return; | 1654 | return; |
1656 | 1655 | ||
1657 | device_set_wakeup_capable(&dev->dev, true); | 1656 | device_set_wakeup_capable(&dev->dev, true); |
1658 | device_set_wakeup_enable(&dev->dev, false); | ||
1659 | platform_pci_sleep_wake(dev, false); | 1657 | platform_pci_sleep_wake(dev, false); |
1660 | } | 1658 | } |
1661 | 1659 | ||
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 4eb10f48d270..f8077b3c8c8c 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -244,7 +244,7 @@ struct pci_ats { | |||
244 | int stu; /* Smallest Translation Unit */ | 244 | int stu; /* Smallest Translation Unit */ |
245 | int qdep; /* Invalidate Queue Depth */ | 245 | int qdep; /* Invalidate Queue Depth */ |
246 | int ref_cnt; /* Physical Function reference count */ | 246 | int ref_cnt; /* Physical Function reference count */ |
247 | int is_enabled:1; /* Enable bit is set */ | 247 | unsigned int is_enabled:1; /* Enable bit is set */ |
248 | }; | 248 | }; |
249 | 249 | ||
250 | #ifdef CONFIG_PCI_IOV | 250 | #ifdef CONFIG_PCI_IOV |
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index f8f425b8731d..909924692b8a 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c | |||
@@ -168,7 +168,7 @@ static u32 *find_pci_config_dword(struct aer_error *err, int where, | |||
168 | target = &err->root_status; | 168 | target = &err->root_status; |
169 | rw1cs = 1; | 169 | rw1cs = 1; |
170 | break; | 170 | break; |
171 | case PCI_ERR_ROOT_COR_SRC: | 171 | case PCI_ERR_ROOT_ERR_SRC: |
172 | target = &err->source_id; | 172 | target = &err->source_id; |
173 | break; | 173 | break; |
174 | } | 174 | } |
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 7a711ee314b7..484cc55194b8 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c | |||
@@ -72,13 +72,120 @@ void pci_no_aer(void) | |||
72 | pcie_aer_disable = 1; /* has priority over 'forceload' */ | 72 | pcie_aer_disable = 1; /* has priority over 'forceload' */ |
73 | } | 73 | } |
74 | 74 | ||
75 | static int set_device_error_reporting(struct pci_dev *dev, void *data) | ||
76 | { | ||
77 | bool enable = *((bool *)data); | ||
78 | |||
79 | if ((dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) || | ||
80 | (dev->pcie_type == PCI_EXP_TYPE_UPSTREAM) || | ||
81 | (dev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)) { | ||
82 | if (enable) | ||
83 | pci_enable_pcie_error_reporting(dev); | ||
84 | else | ||
85 | pci_disable_pcie_error_reporting(dev); | ||
86 | } | ||
87 | |||
88 | if (enable) | ||
89 | pcie_set_ecrc_checking(dev); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * set_downstream_devices_error_reporting - enable/disable the error reporting bits on the root port and its downstream ports. | ||
96 | * @dev: pointer to root port's pci_dev data structure | ||
97 | * @enable: true = enable error reporting, false = disable error reporting. | ||
98 | */ | ||
99 | static void set_downstream_devices_error_reporting(struct pci_dev *dev, | ||
100 | bool enable) | ||
101 | { | ||
102 | set_device_error_reporting(dev, &enable); | ||
103 | |||
104 | if (!dev->subordinate) | ||
105 | return; | ||
106 | pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * aer_enable_rootport - enable Root Port's interrupts when receiving messages | ||
111 | * @rpc: pointer to a Root Port data structure | ||
112 | * | ||
113 | * Invoked when PCIe bus loads AER service driver. | ||
114 | */ | ||
115 | static void aer_enable_rootport(struct aer_rpc *rpc) | ||
116 | { | ||
117 | struct pci_dev *pdev = rpc->rpd->port; | ||
118 | int pos, aer_pos; | ||
119 | u16 reg16; | ||
120 | u32 reg32; | ||
121 | |||
122 | pos = pci_pcie_cap(pdev); | ||
123 | /* Clear PCIe Capability's Device Status */ | ||
124 | pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, ®16); | ||
125 | pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16); | ||
126 | |||
127 | /* Disable system error generation in response to error messages */ | ||
128 | pci_read_config_word(pdev, pos + PCI_EXP_RTCTL, ®16); | ||
129 | reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK); | ||
130 | pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16); | ||
131 | |||
132 | aer_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | ||
133 | /* Clear error status */ | ||
134 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, ®32); | ||
135 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32); | ||
136 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, ®32); | ||
137 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32); | ||
138 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, ®32); | ||
139 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32); | ||
140 | |||
141 | /* | ||
142 | * Enable error reporting for the root port device and downstream port | ||
143 | * devices. | ||
144 | */ | ||
145 | set_downstream_devices_error_reporting(pdev, true); | ||
146 | |||
147 | /* Enable Root Port's interrupt in response to error messages */ | ||
148 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, ®32); | ||
149 | reg32 |= ROOT_PORT_INTR_ON_MESG_MASK; | ||
150 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, reg32); | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * aer_disable_rootport - disable Root Port's interrupts when receiving messages | ||
155 | * @rpc: pointer to a Root Port data structure | ||
156 | * | ||
157 | * Invoked when PCIe bus unloads AER service driver. | ||
158 | */ | ||
159 | static void aer_disable_rootport(struct aer_rpc *rpc) | ||
160 | { | ||
161 | struct pci_dev *pdev = rpc->rpd->port; | ||
162 | u32 reg32; | ||
163 | int pos; | ||
164 | |||
165 | /* | ||
166 | * Disable error reporting for the root port device and downstream port | ||
167 | * devices. | ||
168 | */ | ||
169 | set_downstream_devices_error_reporting(pdev, false); | ||
170 | |||
171 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | ||
172 | /* Disable Root's interrupt in response to error messages */ | ||
173 | pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, ®32); | ||
174 | reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; | ||
175 | pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, reg32); | ||
176 | |||
177 | /* Clear Root's error status reg */ | ||
178 | pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, ®32); | ||
179 | pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32); | ||
180 | } | ||
181 | |||
75 | /** | 182 | /** |
76 | * aer_irq - Root Port's ISR | 183 | * aer_irq - Root Port's ISR |
77 | * @irq: IRQ assigned to Root Port | 184 | * @irq: IRQ assigned to Root Port |
78 | * @context: pointer to Root Port data structure | 185 | * @context: pointer to Root Port data structure |
79 | * | 186 | * |
80 | * Invoked when Root Port detects AER messages. | 187 | * Invoked when Root Port detects AER messages. |
81 | **/ | 188 | */ |
82 | irqreturn_t aer_irq(int irq, void *context) | 189 | irqreturn_t aer_irq(int irq, void *context) |
83 | { | 190 | { |
84 | unsigned int status, id; | 191 | unsigned int status, id; |
@@ -97,13 +204,13 @@ irqreturn_t aer_irq(int irq, void *context) | |||
97 | 204 | ||
98 | /* Read error status */ | 205 | /* Read error status */ |
99 | pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status); | 206 | pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status); |
100 | if (!(status & ROOT_ERR_STATUS_MASKS)) { | 207 | if (!(status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV))) { |
101 | spin_unlock_irqrestore(&rpc->e_lock, flags); | 208 | spin_unlock_irqrestore(&rpc->e_lock, flags); |
102 | return IRQ_NONE; | 209 | return IRQ_NONE; |
103 | } | 210 | } |
104 | 211 | ||
105 | /* Read error source and clear error status */ | 212 | /* Read error source and clear error status */ |
106 | pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_COR_SRC, &id); | 213 | pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_ERR_SRC, &id); |
107 | pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status); | 214 | pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status); |
108 | 215 | ||
109 | /* Store error source for later DPC handler */ | 216 | /* Store error source for later DPC handler */ |
@@ -135,7 +242,7 @@ EXPORT_SYMBOL_GPL(aer_irq); | |||
135 | * @dev: pointer to the pcie_dev data structure | 242 | * @dev: pointer to the pcie_dev data structure |
136 | * | 243 | * |
137 | * Invoked when Root Port's AER service is loaded. | 244 | * Invoked when Root Port's AER service is loaded. |
138 | **/ | 245 | */ |
139 | static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) | 246 | static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) |
140 | { | 247 | { |
141 | struct aer_rpc *rpc; | 248 | struct aer_rpc *rpc; |
@@ -144,15 +251,11 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) | |||
144 | if (!rpc) | 251 | if (!rpc) |
145 | return NULL; | 252 | return NULL; |
146 | 253 | ||
147 | /* | 254 | /* Initialize Root lock access, e_lock, to Root Error Status Reg */ |
148 | * Initialize Root lock access, e_lock, to Root Error Status Reg, | ||
149 | * Root Error ID Reg, and Root error producer/consumer index. | ||
150 | */ | ||
151 | spin_lock_init(&rpc->e_lock); | 255 | spin_lock_init(&rpc->e_lock); |
152 | 256 | ||
153 | rpc->rpd = dev; | 257 | rpc->rpd = dev; |
154 | INIT_WORK(&rpc->dpc_handler, aer_isr); | 258 | INIT_WORK(&rpc->dpc_handler, aer_isr); |
155 | rpc->prod_idx = rpc->cons_idx = 0; | ||
156 | mutex_init(&rpc->rpc_mutex); | 259 | mutex_init(&rpc->rpc_mutex); |
157 | init_waitqueue_head(&rpc->wait_release); | 260 | init_waitqueue_head(&rpc->wait_release); |
158 | 261 | ||
@@ -167,7 +270,7 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) | |||
167 | * @dev: pointer to the pcie_dev data structure | 270 | * @dev: pointer to the pcie_dev data structure |
168 | * | 271 | * |
169 | * Invoked when PCI Express bus unloads or AER probe fails. | 272 | * Invoked when PCI Express bus unloads or AER probe fails. |
170 | **/ | 273 | */ |
171 | static void aer_remove(struct pcie_device *dev) | 274 | static void aer_remove(struct pcie_device *dev) |
172 | { | 275 | { |
173 | struct aer_rpc *rpc = get_service_data(dev); | 276 | struct aer_rpc *rpc = get_service_data(dev); |
@@ -179,7 +282,8 @@ static void aer_remove(struct pcie_device *dev) | |||
179 | 282 | ||
180 | wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx); | 283 | wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx); |
181 | 284 | ||
182 | aer_delete_rootport(rpc); | 285 | aer_disable_rootport(rpc); |
286 | kfree(rpc); | ||
183 | set_service_data(dev, NULL); | 287 | set_service_data(dev, NULL); |
184 | } | 288 | } |
185 | } | 289 | } |
@@ -190,7 +294,7 @@ static void aer_remove(struct pcie_device *dev) | |||
190 | * @id: pointer to the service id data structure | 294 | * @id: pointer to the service id data structure |
191 | * | 295 | * |
192 | * Invoked when PCI Express bus loads AER service driver. | 296 | * Invoked when PCI Express bus loads AER service driver. |
193 | **/ | 297 | */ |
194 | static int __devinit aer_probe(struct pcie_device *dev) | 298 | static int __devinit aer_probe(struct pcie_device *dev) |
195 | { | 299 | { |
196 | int status; | 300 | int status; |
@@ -230,47 +334,30 @@ static int __devinit aer_probe(struct pcie_device *dev) | |||
230 | * @dev: pointer to Root Port's pci_dev data structure | 334 | * @dev: pointer to Root Port's pci_dev data structure |
231 | * | 335 | * |
232 | * Invoked by Port Bus driver when performing link reset at Root Port. | 336 | * Invoked by Port Bus driver when performing link reset at Root Port. |
233 | **/ | 337 | */ |
234 | static pci_ers_result_t aer_root_reset(struct pci_dev *dev) | 338 | static pci_ers_result_t aer_root_reset(struct pci_dev *dev) |
235 | { | 339 | { |
236 | u16 p2p_ctrl; | 340 | u32 reg32; |
237 | u32 status; | ||
238 | int pos; | 341 | int pos; |
239 | 342 | ||
240 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 343 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); |
241 | 344 | ||
242 | /* Disable Root's interrupt in response to error messages */ | 345 | /* Disable Root's interrupt in response to error messages */ |
243 | pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, 0); | 346 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ®32); |
244 | 347 | reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; | |
245 | /* Assert Secondary Bus Reset */ | 348 | pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32); |
246 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &p2p_ctrl); | ||
247 | p2p_ctrl |= PCI_BRIDGE_CTL_BUS_RESET; | ||
248 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl); | ||
249 | |||
250 | /* | ||
251 | * we should send hot reset message for 2ms to allow it time to | ||
252 | * propogate to all downstream ports | ||
253 | */ | ||
254 | msleep(2); | ||
255 | |||
256 | /* De-assert Secondary Bus Reset */ | ||
257 | p2p_ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; | ||
258 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl); | ||
259 | 349 | ||
260 | /* | 350 | aer_do_secondary_bus_reset(dev); |
261 | * System software must wait for at least 100ms from the end | ||
262 | * of a reset of one or more device before it is permitted | ||
263 | * to issue Configuration Requests to those devices. | ||
264 | */ | ||
265 | msleep(200); | ||
266 | dev_printk(KERN_DEBUG, &dev->dev, "Root Port link has been reset\n"); | 351 | dev_printk(KERN_DEBUG, &dev->dev, "Root Port link has been reset\n"); |
267 | 352 | ||
353 | /* Clear Root Error Status */ | ||
354 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, ®32); | ||
355 | pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, reg32); | ||
356 | |||
268 | /* Enable Root Port's interrupt in response to error messages */ | 357 | /* Enable Root Port's interrupt in response to error messages */ |
269 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status); | 358 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ®32); |
270 | pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status); | 359 | reg32 |= ROOT_PORT_INTR_ON_MESG_MASK; |
271 | pci_write_config_dword(dev, | 360 | pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32); |
272 | pos + PCI_ERR_ROOT_COMMAND, | ||
273 | ROOT_PORT_INTR_ON_MESG_MASK); | ||
274 | 361 | ||
275 | return PCI_ERS_RESULT_RECOVERED; | 362 | return PCI_ERS_RESULT_RECOVERED; |
276 | } | 363 | } |
@@ -281,7 +368,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) | |||
281 | * @error: error severity being notified by port bus | 368 | * @error: error severity being notified by port bus |
282 | * | 369 | * |
283 | * Invoked by Port Bus driver during error recovery. | 370 | * Invoked by Port Bus driver during error recovery. |
284 | **/ | 371 | */ |
285 | static pci_ers_result_t aer_error_detected(struct pci_dev *dev, | 372 | static pci_ers_result_t aer_error_detected(struct pci_dev *dev, |
286 | enum pci_channel_state error) | 373 | enum pci_channel_state error) |
287 | { | 374 | { |
@@ -294,7 +381,7 @@ static pci_ers_result_t aer_error_detected(struct pci_dev *dev, | |||
294 | * @dev: pointer to Root Port's pci_dev data structure | 381 | * @dev: pointer to Root Port's pci_dev data structure |
295 | * | 382 | * |
296 | * Invoked by Port Bus driver during nonfatal recovery. | 383 | * Invoked by Port Bus driver during nonfatal recovery. |
297 | **/ | 384 | */ |
298 | static void aer_error_resume(struct pci_dev *dev) | 385 | static void aer_error_resume(struct pci_dev *dev) |
299 | { | 386 | { |
300 | int pos; | 387 | int pos; |
@@ -321,7 +408,7 @@ static void aer_error_resume(struct pci_dev *dev) | |||
321 | * aer_service_init - register AER root service driver | 408 | * aer_service_init - register AER root service driver |
322 | * | 409 | * |
323 | * Invoked when AER root service driver is loaded. | 410 | * Invoked when AER root service driver is loaded. |
324 | **/ | 411 | */ |
325 | static int __init aer_service_init(void) | 412 | static int __init aer_service_init(void) |
326 | { | 413 | { |
327 | if (pcie_aer_disable) | 414 | if (pcie_aer_disable) |
@@ -335,7 +422,7 @@ static int __init aer_service_init(void) | |||
335 | * aer_service_exit - unregister AER root service driver | 422 | * aer_service_exit - unregister AER root service driver |
336 | * | 423 | * |
337 | * Invoked when AER root service driver is unloaded. | 424 | * Invoked when AER root service driver is unloaded. |
338 | **/ | 425 | */ |
339 | static void __exit aer_service_exit(void) | 426 | static void __exit aer_service_exit(void) |
340 | { | 427 | { |
341 | pcie_port_service_unregister(&aerdriver); | 428 | pcie_port_service_unregister(&aerdriver); |
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index bd833ea3ba49..7aaae2d2bd67 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h | |||
@@ -17,9 +17,6 @@ | |||
17 | #define AER_FATAL 1 | 17 | #define AER_FATAL 1 |
18 | #define AER_CORRECTABLE 2 | 18 | #define AER_CORRECTABLE 2 |
19 | 19 | ||
20 | /* Root Error Status Register Bits */ | ||
21 | #define ROOT_ERR_STATUS_MASKS 0x0f | ||
22 | |||
23 | #define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \ | 20 | #define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \ |
24 | PCI_EXP_RTCTL_SENFEE| \ | 21 | PCI_EXP_RTCTL_SENFEE| \ |
25 | PCI_EXP_RTCTL_SEFEE) | 22 | PCI_EXP_RTCTL_SEFEE) |
@@ -117,8 +114,7 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig, | |||
117 | } | 114 | } |
118 | 115 | ||
119 | extern struct bus_type pcie_port_bus_type; | 116 | extern struct bus_type pcie_port_bus_type; |
120 | extern void aer_enable_rootport(struct aer_rpc *rpc); | 117 | extern void aer_do_secondary_bus_reset(struct pci_dev *dev); |
121 | extern void aer_delete_rootport(struct aer_rpc *rpc); | ||
122 | extern int aer_init(struct pcie_device *dev); | 118 | extern int aer_init(struct pcie_device *dev); |
123 | extern void aer_isr(struct work_struct *work); | 119 | extern void aer_isr(struct work_struct *work); |
124 | extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); | 120 | extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index aceb04b67b60..df2d686fe3dd 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -47,13 +47,12 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev) | |||
47 | if (!pos) | 47 | if (!pos) |
48 | return -EIO; | 48 | return -EIO; |
49 | 49 | ||
50 | pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, ®16); | 50 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); |
51 | reg16 = reg16 | | 51 | reg16 |= (PCI_EXP_DEVCTL_CERE | |
52 | PCI_EXP_DEVCTL_CERE | | ||
53 | PCI_EXP_DEVCTL_NFERE | | 52 | PCI_EXP_DEVCTL_NFERE | |
54 | PCI_EXP_DEVCTL_FERE | | 53 | PCI_EXP_DEVCTL_FERE | |
55 | PCI_EXP_DEVCTL_URRE; | 54 | PCI_EXP_DEVCTL_URRE); |
56 | pci_write_config_word(dev, pos+PCI_EXP_DEVCTL, reg16); | 55 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); |
57 | 56 | ||
58 | return 0; | 57 | return 0; |
59 | } | 58 | } |
@@ -71,12 +70,12 @@ int pci_disable_pcie_error_reporting(struct pci_dev *dev) | |||
71 | if (!pos) | 70 | if (!pos) |
72 | return -EIO; | 71 | return -EIO; |
73 | 72 | ||
74 | pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, ®16); | 73 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); |
75 | reg16 = reg16 & ~(PCI_EXP_DEVCTL_CERE | | 74 | reg16 &= ~(PCI_EXP_DEVCTL_CERE | |
76 | PCI_EXP_DEVCTL_NFERE | | 75 | PCI_EXP_DEVCTL_NFERE | |
77 | PCI_EXP_DEVCTL_FERE | | 76 | PCI_EXP_DEVCTL_FERE | |
78 | PCI_EXP_DEVCTL_URRE); | 77 | PCI_EXP_DEVCTL_URRE); |
79 | pci_write_config_word(dev, pos+PCI_EXP_DEVCTL, reg16); | 78 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); |
80 | 79 | ||
81 | return 0; | 80 | return 0; |
82 | } | 81 | } |
@@ -99,99 +98,46 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) | |||
99 | } | 98 | } |
100 | EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); | 99 | EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); |
101 | 100 | ||
102 | static int set_device_error_reporting(struct pci_dev *dev, void *data) | ||
103 | { | ||
104 | bool enable = *((bool *)data); | ||
105 | |||
106 | if ((dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) || | ||
107 | (dev->pcie_type == PCI_EXP_TYPE_UPSTREAM) || | ||
108 | (dev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)) { | ||
109 | if (enable) | ||
110 | pci_enable_pcie_error_reporting(dev); | ||
111 | else | ||
112 | pci_disable_pcie_error_reporting(dev); | ||
113 | } | ||
114 | |||
115 | if (enable) | ||
116 | pcie_set_ecrc_checking(dev); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | /** | 101 | /** |
122 | * set_downstream_devices_error_reporting - enable/disable the error reporting bits on the root port and its downstream ports. | 102 | * add_error_device - list device to be handled |
123 | * @dev: pointer to root port's pci_dev data structure | 103 | * @e_info: pointer to error info |
124 | * @enable: true = enable error reporting, false = disable error reporting. | 104 | * @dev: pointer to pci_dev to be added |
125 | */ | 105 | */ |
126 | static void set_downstream_devices_error_reporting(struct pci_dev *dev, | ||
127 | bool enable) | ||
128 | { | ||
129 | set_device_error_reporting(dev, &enable); | ||
130 | |||
131 | if (!dev->subordinate) | ||
132 | return; | ||
133 | pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable); | ||
134 | } | ||
135 | |||
136 | static inline int compare_device_id(struct pci_dev *dev, | ||
137 | struct aer_err_info *e_info) | ||
138 | { | ||
139 | if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) { | ||
140 | /* | ||
141 | * Device ID match | ||
142 | */ | ||
143 | return 1; | ||
144 | } | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev) | 106 | static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev) |
150 | { | 107 | { |
151 | if (e_info->error_dev_num < AER_MAX_MULTI_ERR_DEVICES) { | 108 | if (e_info->error_dev_num < AER_MAX_MULTI_ERR_DEVICES) { |
152 | e_info->dev[e_info->error_dev_num] = dev; | 109 | e_info->dev[e_info->error_dev_num] = dev; |
153 | e_info->error_dev_num++; | 110 | e_info->error_dev_num++; |
154 | return 1; | 111 | return 0; |
155 | } | 112 | } |
156 | 113 | return -ENOSPC; | |
157 | return 0; | ||
158 | } | 114 | } |
159 | 115 | ||
160 | |||
161 | #define PCI_BUS(x) (((x) >> 8) & 0xff) | 116 | #define PCI_BUS(x) (((x) >> 8) & 0xff) |
162 | 117 | ||
163 | static int find_device_iter(struct pci_dev *dev, void *data) | 118 | /** |
119 | * is_error_source - check whether the device is source of reported error | ||
120 | * @dev: pointer to pci_dev to be checked | ||
121 | * @e_info: pointer to reported error info | ||
122 | */ | ||
123 | static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) | ||
164 | { | 124 | { |
165 | int pos; | 125 | int pos; |
166 | u32 status; | 126 | u32 status, mask; |
167 | u32 mask; | ||
168 | u16 reg16; | 127 | u16 reg16; |
169 | int result; | ||
170 | struct aer_err_info *e_info = (struct aer_err_info *)data; | ||
171 | 128 | ||
172 | /* | 129 | /* |
173 | * When bus id is equal to 0, it might be a bad id | 130 | * When bus id is equal to 0, it might be a bad id |
174 | * reported by root port. | 131 | * reported by root port. |
175 | */ | 132 | */ |
176 | if (!nosourceid && (PCI_BUS(e_info->id) != 0)) { | 133 | if (!nosourceid && (PCI_BUS(e_info->id) != 0)) { |
177 | result = compare_device_id(dev, e_info); | 134 | /* Device ID match? */ |
178 | if (result) | 135 | if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) |
179 | add_error_device(e_info, dev); | 136 | return true; |
180 | 137 | ||
181 | /* | 138 | /* Continue id comparing if there is no multiple error */ |
182 | * If there is no multiple error, we stop | ||
183 | * or continue based on the id comparing. | ||
184 | */ | ||
185 | if (!e_info->multi_error_valid) | 139 | if (!e_info->multi_error_valid) |
186 | return result; | 140 | return false; |
187 | |||
188 | /* | ||
189 | * If there are multiple errors and id does match, | ||
190 | * We need continue to search other devices under | ||
191 | * the root port. Return 0 means that. | ||
192 | */ | ||
193 | if (result) | ||
194 | return 0; | ||
195 | } | 141 | } |
196 | 142 | ||
197 | /* | 143 | /* |
@@ -200,71 +146,94 @@ static int find_device_iter(struct pci_dev *dev, void *data) | |||
200 | * 2) bus id is equal to 0. Some ports might lose the bus | 146 | * 2) bus id is equal to 0. Some ports might lose the bus |
201 | * id of error source id; | 147 | * id of error source id; |
202 | * 3) There are multiple errors and prior id comparing fails; | 148 | * 3) There are multiple errors and prior id comparing fails; |
203 | * We check AER status registers to find the initial reporter. | 149 | * We check AER status registers to find possible reporter. |
204 | */ | 150 | */ |
205 | if (atomic_read(&dev->enable_cnt) == 0) | 151 | if (atomic_read(&dev->enable_cnt) == 0) |
206 | return 0; | 152 | return false; |
207 | pos = pci_pcie_cap(dev); | 153 | pos = pci_pcie_cap(dev); |
208 | if (!pos) | 154 | if (!pos) |
209 | return 0; | 155 | return false; |
156 | |||
210 | /* Check if AER is enabled */ | 157 | /* Check if AER is enabled */ |
211 | pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, ®16); | 158 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); |
212 | if (!(reg16 & ( | 159 | if (!(reg16 & ( |
213 | PCI_EXP_DEVCTL_CERE | | 160 | PCI_EXP_DEVCTL_CERE | |
214 | PCI_EXP_DEVCTL_NFERE | | 161 | PCI_EXP_DEVCTL_NFERE | |
215 | PCI_EXP_DEVCTL_FERE | | 162 | PCI_EXP_DEVCTL_FERE | |
216 | PCI_EXP_DEVCTL_URRE))) | 163 | PCI_EXP_DEVCTL_URRE))) |
217 | return 0; | 164 | return false; |
218 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 165 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); |
219 | if (!pos) | 166 | if (!pos) |
220 | return 0; | 167 | return false; |
221 | 168 | ||
222 | status = 0; | 169 | /* Check if error is recorded */ |
223 | mask = 0; | ||
224 | if (e_info->severity == AER_CORRECTABLE) { | 170 | if (e_info->severity == AER_CORRECTABLE) { |
225 | pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status); | 171 | pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status); |
226 | pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &mask); | 172 | pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &mask); |
227 | if (status & ~mask) { | ||
228 | add_error_device(e_info, dev); | ||
229 | goto added; | ||
230 | } | ||
231 | } else { | 173 | } else { |
232 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); | 174 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); |
233 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &mask); | 175 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &mask); |
234 | if (status & ~mask) { | ||
235 | add_error_device(e_info, dev); | ||
236 | goto added; | ||
237 | } | ||
238 | } | 176 | } |
177 | if (status & ~mask) | ||
178 | return true; | ||
239 | 179 | ||
240 | return 0; | 180 | return false; |
181 | } | ||
241 | 182 | ||
242 | added: | 183 | static int find_device_iter(struct pci_dev *dev, void *data) |
243 | if (e_info->multi_error_valid) | 184 | { |
244 | return 0; | 185 | struct aer_err_info *e_info = (struct aer_err_info *)data; |
245 | else | 186 | |
246 | return 1; | 187 | if (is_error_source(dev, e_info)) { |
188 | /* List this device */ | ||
189 | if (add_error_device(e_info, dev)) { | ||
190 | /* We cannot handle more... Stop iteration */ | ||
191 | /* TODO: Should print error message here? */ | ||
192 | return 1; | ||
193 | } | ||
194 | |||
195 | /* If there is only a single error, stop iteration */ | ||
196 | if (!e_info->multi_error_valid) | ||
197 | return 1; | ||
198 | } | ||
199 | return 0; | ||
247 | } | 200 | } |
248 | 201 | ||
249 | /** | 202 | /** |
250 | * find_source_device - search through device hierarchy for source device | 203 | * find_source_device - search through device hierarchy for source device |
251 | * @parent: pointer to Root Port pci_dev data structure | 204 | * @parent: pointer to Root Port pci_dev data structure |
252 | * @err_info: including detailed error information such like id | 205 | * @e_info: including detailed error information such like id |
253 | * | 206 | * |
254 | * Invoked when error is detected at the Root Port. | 207 | * Return true if found. |
208 | * | ||
209 | * Invoked by DPC when error is detected at the Root Port. | ||
210 | * Caller of this function must set id, severity, and multi_error_valid of | ||
211 | * struct aer_err_info pointed by @e_info properly. This function must fill | ||
212 | * e_info->error_dev_num and e_info->dev[], based on the given information. | ||
255 | */ | 213 | */ |
256 | static void find_source_device(struct pci_dev *parent, | 214 | static bool find_source_device(struct pci_dev *parent, |
257 | struct aer_err_info *e_info) | 215 | struct aer_err_info *e_info) |
258 | { | 216 | { |
259 | struct pci_dev *dev = parent; | 217 | struct pci_dev *dev = parent; |
260 | int result; | 218 | int result; |
261 | 219 | ||
220 | /* Must reset in this function */ | ||
221 | e_info->error_dev_num = 0; | ||
222 | |||
262 | /* Is Root Port an agent that sends error message? */ | 223 | /* Is Root Port an agent that sends error message? */ |
263 | result = find_device_iter(dev, e_info); | 224 | result = find_device_iter(dev, e_info); |
264 | if (result) | 225 | if (result) |
265 | return; | 226 | return true; |
266 | 227 | ||
267 | pci_walk_bus(parent->subordinate, find_device_iter, e_info); | 228 | pci_walk_bus(parent->subordinate, find_device_iter, e_info); |
229 | |||
230 | if (!e_info->error_dev_num) { | ||
231 | dev_printk(KERN_DEBUG, &parent->dev, | ||
232 | "can't find device of ID%04x\n", | ||
233 | e_info->id); | ||
234 | return false; | ||
235 | } | ||
236 | return true; | ||
268 | } | 237 | } |
269 | 238 | ||
270 | static int report_error_detected(struct pci_dev *dev, void *data) | 239 | static int report_error_detected(struct pci_dev *dev, void *data) |
@@ -403,43 +372,77 @@ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev, | |||
403 | return result_data.result; | 372 | return result_data.result; |
404 | } | 373 | } |
405 | 374 | ||
406 | struct find_aer_service_data { | 375 | /** |
407 | struct pcie_port_service_driver *aer_driver; | 376 | * aer_do_secondary_bus_reset - perform secondary bus reset |
408 | int is_downstream; | 377 | * @dev: pointer to bridge's pci_dev data structure |
409 | }; | 378 | * |
410 | 379 | * Invoked when performing link reset at Root Port or Downstream Port. | |
411 | static int find_aer_service_iter(struct device *device, void *data) | 380 | */ |
381 | void aer_do_secondary_bus_reset(struct pci_dev *dev) | ||
412 | { | 382 | { |
413 | struct device_driver *driver; | 383 | u16 p2p_ctrl; |
414 | struct pcie_port_service_driver *service_driver; | 384 | |
415 | struct find_aer_service_data *result; | 385 | /* Assert Secondary Bus Reset */ |
386 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &p2p_ctrl); | ||
387 | p2p_ctrl |= PCI_BRIDGE_CTL_BUS_RESET; | ||
388 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl); | ||
389 | |||
390 | /* | ||
391 | * we should send hot reset message for 2ms to allow it time to | ||
392 | * propagate to all downstream ports | ||
393 | */ | ||
394 | msleep(2); | ||
395 | |||
396 | /* De-assert Secondary Bus Reset */ | ||
397 | p2p_ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET; | ||
398 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl); | ||
399 | |||
400 | /* | ||
401 | * System software must wait for at least 100ms from the end | ||
402 | * of a reset of one or more device before it is permitted | ||
403 | * to issue Configuration Requests to those devices. | ||
404 | */ | ||
405 | msleep(200); | ||
406 | } | ||
416 | 407 | ||
417 | result = (struct find_aer_service_data *) data; | 408 | /** |
409 | * default_downstream_reset_link - default reset function for Downstream Port | ||
410 | * @dev: pointer to downstream port's pci_dev data structure | ||
411 | * | ||
412 | * Invoked when performing link reset at Downstream Port w/ no aer driver. | ||
413 | */ | ||
414 | static pci_ers_result_t default_downstream_reset_link(struct pci_dev *dev) | ||
415 | { | ||
416 | aer_do_secondary_bus_reset(dev); | ||
417 | dev_printk(KERN_DEBUG, &dev->dev, | ||
418 | "Downstream Port link has been reset\n"); | ||
419 | return PCI_ERS_RESULT_RECOVERED; | ||
420 | } | ||
418 | 421 | ||
419 | if (device->bus == &pcie_port_bus_type) { | 422 | static int find_aer_service_iter(struct device *device, void *data) |
420 | struct pcie_device *pcie = to_pcie_device(device); | 423 | { |
424 | struct pcie_port_service_driver *service_driver, **drv; | ||
421 | 425 | ||
422 | if (pcie->port->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) | 426 | drv = (struct pcie_port_service_driver **) data; |
423 | result->is_downstream = 1; | ||
424 | 427 | ||
425 | driver = device->driver; | 428 | if (device->bus == &pcie_port_bus_type && device->driver) { |
426 | if (driver) { | 429 | service_driver = to_service_driver(device->driver); |
427 | service_driver = to_service_driver(driver); | 430 | if (service_driver->service == PCIE_PORT_SERVICE_AER) { |
428 | if (service_driver->service == PCIE_PORT_SERVICE_AER) { | 431 | *drv = service_driver; |
429 | result->aer_driver = service_driver; | 432 | return 1; |
430 | return 1; | ||
431 | } | ||
432 | } | 433 | } |
433 | } | 434 | } |
434 | 435 | ||
435 | return 0; | 436 | return 0; |
436 | } | 437 | } |
437 | 438 | ||
438 | static void find_aer_service(struct pci_dev *dev, | 439 | static struct pcie_port_service_driver *find_aer_service(struct pci_dev *dev) |
439 | struct find_aer_service_data *data) | ||
440 | { | 440 | { |
441 | int retval; | 441 | struct pcie_port_service_driver *drv = NULL; |
442 | retval = device_for_each_child(&dev->dev, data, find_aer_service_iter); | 442 | |
443 | device_for_each_child(&dev->dev, &drv, find_aer_service_iter); | ||
444 | |||
445 | return drv; | ||
443 | } | 446 | } |
444 | 447 | ||
445 | static pci_ers_result_t reset_link(struct pcie_device *aerdev, | 448 | static pci_ers_result_t reset_link(struct pcie_device *aerdev, |
@@ -447,38 +450,34 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev, | |||
447 | { | 450 | { |
448 | struct pci_dev *udev; | 451 | struct pci_dev *udev; |
449 | pci_ers_result_t status; | 452 | pci_ers_result_t status; |
450 | struct find_aer_service_data data; | 453 | struct pcie_port_service_driver *driver; |
451 | 454 | ||
452 | if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) | 455 | if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) { |
456 | /* Reset this port for all subordinates */ | ||
453 | udev = dev; | 457 | udev = dev; |
454 | else | 458 | } else { |
459 | /* Reset the upstream component (likely downstream port) */ | ||
455 | udev = dev->bus->self; | 460 | udev = dev->bus->self; |
461 | } | ||
456 | 462 | ||
457 | data.is_downstream = 0; | 463 | /* Use the aer driver of the component firstly */ |
458 | data.aer_driver = NULL; | 464 | driver = find_aer_service(udev); |
459 | find_aer_service(udev, &data); | ||
460 | 465 | ||
461 | /* | 466 | if (driver && driver->reset_link) { |
462 | * Use the aer driver of the error agent firstly. | 467 | status = driver->reset_link(udev); |
463 | * If it hasn't the aer driver, use the root port's | 468 | } else if (udev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) { |
464 | */ | 469 | status = default_downstream_reset_link(udev); |
465 | if (!data.aer_driver || !data.aer_driver->reset_link) { | 470 | } else { |
466 | if (data.is_downstream && | 471 | dev_printk(KERN_DEBUG, &dev->dev, |
467 | aerdev->device.driver && | 472 | "no link-reset support at upstream device %s\n", |
468 | to_service_driver(aerdev->device.driver)->reset_link) { | 473 | pci_name(udev)); |
469 | data.aer_driver = | 474 | return PCI_ERS_RESULT_DISCONNECT; |
470 | to_service_driver(aerdev->device.driver); | ||
471 | } else { | ||
472 | dev_printk(KERN_DEBUG, &dev->dev, "no link-reset " | ||
473 | "support\n"); | ||
474 | return PCI_ERS_RESULT_DISCONNECT; | ||
475 | } | ||
476 | } | 475 | } |
477 | 476 | ||
478 | status = data.aer_driver->reset_link(udev); | ||
479 | if (status != PCI_ERS_RESULT_RECOVERED) { | 477 | if (status != PCI_ERS_RESULT_RECOVERED) { |
480 | dev_printk(KERN_DEBUG, &dev->dev, "link reset at upstream " | 478 | dev_printk(KERN_DEBUG, &dev->dev, |
481 | "device %s failed\n", pci_name(udev)); | 479 | "link reset at upstream device %s failed\n", |
480 | pci_name(udev)); | ||
482 | return PCI_ERS_RESULT_DISCONNECT; | 481 | return PCI_ERS_RESULT_DISCONNECT; |
483 | } | 482 | } |
484 | 483 | ||
@@ -495,8 +494,7 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev, | |||
495 | * error detected message to all downstream drivers within a hierarchy in | 494 | * error detected message to all downstream drivers within a hierarchy in |
496 | * question and return the returned code. | 495 | * question and return the returned code. |
497 | */ | 496 | */ |
498 | static pci_ers_result_t do_recovery(struct pcie_device *aerdev, | 497 | static void do_recovery(struct pcie_device *aerdev, struct pci_dev *dev, |
499 | struct pci_dev *dev, | ||
500 | int severity) | 498 | int severity) |
501 | { | 499 | { |
502 | pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED; | 500 | pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED; |
@@ -514,10 +512,8 @@ static pci_ers_result_t do_recovery(struct pcie_device *aerdev, | |||
514 | 512 | ||
515 | if (severity == AER_FATAL) { | 513 | if (severity == AER_FATAL) { |
516 | result = reset_link(aerdev, dev); | 514 | result = reset_link(aerdev, dev); |
517 | if (result != PCI_ERS_RESULT_RECOVERED) { | 515 | if (result != PCI_ERS_RESULT_RECOVERED) |
518 | /* TODO: Should panic here? */ | 516 | goto failed; |
519 | return result; | ||
520 | } | ||
521 | } | 517 | } |
522 | 518 | ||
523 | if (status == PCI_ERS_RESULT_CAN_RECOVER) | 519 | if (status == PCI_ERS_RESULT_CAN_RECOVER) |
@@ -538,13 +534,22 @@ static pci_ers_result_t do_recovery(struct pcie_device *aerdev, | |||
538 | report_slot_reset); | 534 | report_slot_reset); |
539 | } | 535 | } |
540 | 536 | ||
541 | if (status == PCI_ERS_RESULT_RECOVERED) | 537 | if (status != PCI_ERS_RESULT_RECOVERED) |
542 | broadcast_error_message(dev, | 538 | goto failed; |
539 | |||
540 | broadcast_error_message(dev, | ||
543 | state, | 541 | state, |
544 | "resume", | 542 | "resume", |
545 | report_resume); | 543 | report_resume); |
546 | 544 | ||
547 | return status; | 545 | dev_printk(KERN_DEBUG, &dev->dev, |
546 | "AER driver successfully recovered\n"); | ||
547 | return; | ||
548 | |||
549 | failed: | ||
550 | /* TODO: Should kernel panic here? */ | ||
551 | dev_printk(KERN_DEBUG, &dev->dev, | ||
552 | "AER driver didn't recover\n"); | ||
548 | } | 553 | } |
549 | 554 | ||
550 | /** | 555 | /** |
@@ -559,7 +564,6 @@ static void handle_error_source(struct pcie_device *aerdev, | |||
559 | struct pci_dev *dev, | 564 | struct pci_dev *dev, |
560 | struct aer_err_info *info) | 565 | struct aer_err_info *info) |
561 | { | 566 | { |
562 | pci_ers_result_t status = 0; | ||
563 | int pos; | 567 | int pos; |
564 | 568 | ||
565 | if (info->severity == AER_CORRECTABLE) { | 569 | if (info->severity == AER_CORRECTABLE) { |
@@ -571,114 +575,8 @@ static void handle_error_source(struct pcie_device *aerdev, | |||
571 | if (pos) | 575 | if (pos) |
572 | pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, | 576 | pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, |
573 | info->status); | 577 | info->status); |
574 | } else { | 578 | } else |
575 | status = do_recovery(aerdev, dev, info->severity); | 579 | do_recovery(aerdev, dev, info->severity); |
576 | if (status == PCI_ERS_RESULT_RECOVERED) { | ||
577 | dev_printk(KERN_DEBUG, &dev->dev, "AER driver " | ||
578 | "successfully recovered\n"); | ||
579 | } else { | ||
580 | /* TODO: Should kernel panic here? */ | ||
581 | dev_printk(KERN_DEBUG, &dev->dev, "AER driver didn't " | ||
582 | "recover\n"); | ||
583 | } | ||
584 | } | ||
585 | } | ||
586 | |||
587 | /** | ||
588 | * aer_enable_rootport - enable Root Port's interrupts when receiving messages | ||
589 | * @rpc: pointer to a Root Port data structure | ||
590 | * | ||
591 | * Invoked when PCIe bus loads AER service driver. | ||
592 | */ | ||
593 | void aer_enable_rootport(struct aer_rpc *rpc) | ||
594 | { | ||
595 | struct pci_dev *pdev = rpc->rpd->port; | ||
596 | int pos, aer_pos; | ||
597 | u16 reg16; | ||
598 | u32 reg32; | ||
599 | |||
600 | pos = pci_pcie_cap(pdev); | ||
601 | /* Clear PCIe Capability's Device Status */ | ||
602 | pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, ®16); | ||
603 | pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16); | ||
604 | |||
605 | /* Disable system error generation in response to error messages */ | ||
606 | pci_read_config_word(pdev, pos + PCI_EXP_RTCTL, ®16); | ||
607 | reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK); | ||
608 | pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16); | ||
609 | |||
610 | aer_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | ||
611 | /* Clear error status */ | ||
612 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, ®32); | ||
613 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32); | ||
614 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, ®32); | ||
615 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32); | ||
616 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, ®32); | ||
617 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32); | ||
618 | |||
619 | /* | ||
620 | * Enable error reporting for the root port device and downstream port | ||
621 | * devices. | ||
622 | */ | ||
623 | set_downstream_devices_error_reporting(pdev, true); | ||
624 | |||
625 | /* Enable Root Port's interrupt in response to error messages */ | ||
626 | pci_write_config_dword(pdev, | ||
627 | aer_pos + PCI_ERR_ROOT_COMMAND, | ||
628 | ROOT_PORT_INTR_ON_MESG_MASK); | ||
629 | } | ||
630 | |||
631 | /** | ||
632 | * disable_root_aer - disable Root Port's interrupts when receiving messages | ||
633 | * @rpc: pointer to a Root Port data structure | ||
634 | * | ||
635 | * Invoked when PCIe bus unloads AER service driver. | ||
636 | */ | ||
637 | static void disable_root_aer(struct aer_rpc *rpc) | ||
638 | { | ||
639 | struct pci_dev *pdev = rpc->rpd->port; | ||
640 | u32 reg32; | ||
641 | int pos; | ||
642 | |||
643 | /* | ||
644 | * Disable error reporting for the root port device and downstream port | ||
645 | * devices. | ||
646 | */ | ||
647 | set_downstream_devices_error_reporting(pdev, false); | ||
648 | |||
649 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | ||
650 | /* Disable Root's interrupt in response to error messages */ | ||
651 | pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0); | ||
652 | |||
653 | /* Clear Root's error status reg */ | ||
654 | pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, ®32); | ||
655 | pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32); | ||
656 | } | ||
657 | |||
658 | /** | ||
659 | * get_e_source - retrieve an error source | ||
660 | * @rpc: pointer to the root port which holds an error | ||
661 | * | ||
662 | * Invoked by DPC handler to consume an error. | ||
663 | */ | ||
664 | static struct aer_err_source *get_e_source(struct aer_rpc *rpc) | ||
665 | { | ||
666 | struct aer_err_source *e_source; | ||
667 | unsigned long flags; | ||
668 | |||
669 | /* Lock access to Root error producer/consumer index */ | ||
670 | spin_lock_irqsave(&rpc->e_lock, flags); | ||
671 | if (rpc->prod_idx == rpc->cons_idx) { | ||
672 | spin_unlock_irqrestore(&rpc->e_lock, flags); | ||
673 | return NULL; | ||
674 | } | ||
675 | e_source = &rpc->e_sources[rpc->cons_idx]; | ||
676 | rpc->cons_idx++; | ||
677 | if (rpc->cons_idx == AER_ERROR_SOURCES_MAX) | ||
678 | rpc->cons_idx = 0; | ||
679 | spin_unlock_irqrestore(&rpc->e_lock, flags); | ||
680 | |||
681 | return e_source; | ||
682 | } | 580 | } |
683 | 581 | ||
684 | /** | 582 | /** |
@@ -687,11 +585,14 @@ static struct aer_err_source *get_e_source(struct aer_rpc *rpc) | |||
687 | * @info: pointer to structure to store the error record | 585 | * @info: pointer to structure to store the error record |
688 | * | 586 | * |
689 | * Return 1 on success, 0 on error. | 587 | * Return 1 on success, 0 on error. |
588 | * | ||
589 | * Note that @info is reused among all error devices. Clear fields properly. | ||
690 | */ | 590 | */ |
691 | static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) | 591 | static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) |
692 | { | 592 | { |
693 | int pos, temp; | 593 | int pos, temp; |
694 | 594 | ||
595 | /* Must reset in this function */ | ||
695 | info->status = 0; | 596 | info->status = 0; |
696 | info->tlp_header_valid = 0; | 597 | info->tlp_header_valid = 0; |
697 | 598 | ||
@@ -744,12 +645,6 @@ static inline void aer_process_err_devices(struct pcie_device *p_device, | |||
744 | { | 645 | { |
745 | int i; | 646 | int i; |
746 | 647 | ||
747 | if (!e_info->dev[0]) { | ||
748 | dev_printk(KERN_DEBUG, &p_device->port->dev, | ||
749 | "can't find device of ID%04x\n", | ||
750 | e_info->id); | ||
751 | } | ||
752 | |||
753 | /* Report all before handle them, not to lost records by reset etc. */ | 648 | /* Report all before handle them, not to lost records by reset etc. */ |
754 | for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) { | 649 | for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) { |
755 | if (get_device_error_info(e_info->dev[i], e_info)) | 650 | if (get_device_error_info(e_info->dev[i], e_info)) |
@@ -770,11 +665,10 @@ static void aer_isr_one_error(struct pcie_device *p_device, | |||
770 | struct aer_err_source *e_src) | 665 | struct aer_err_source *e_src) |
771 | { | 666 | { |
772 | struct aer_err_info *e_info; | 667 | struct aer_err_info *e_info; |
773 | int i; | ||
774 | 668 | ||
775 | /* struct aer_err_info might be big, so we allocate it with slab */ | 669 | /* struct aer_err_info might be big, so we allocate it with slab */ |
776 | e_info = kmalloc(sizeof(struct aer_err_info), GFP_KERNEL); | 670 | e_info = kmalloc(sizeof(struct aer_err_info), GFP_KERNEL); |
777 | if (e_info == NULL) { | 671 | if (!e_info) { |
778 | dev_printk(KERN_DEBUG, &p_device->port->dev, | 672 | dev_printk(KERN_DEBUG, &p_device->port->dev, |
779 | "Can't allocate mem when processing AER errors\n"); | 673 | "Can't allocate mem when processing AER errors\n"); |
780 | return; | 674 | return; |
@@ -784,37 +678,72 @@ static void aer_isr_one_error(struct pcie_device *p_device, | |||
784 | * There is a possibility that both correctable error and | 678 | * There is a possibility that both correctable error and |
785 | * uncorrectable error being logged. Report correctable error first. | 679 | * uncorrectable error being logged. Report correctable error first. |
786 | */ | 680 | */ |
787 | for (i = 1; i & ROOT_ERR_STATUS_MASKS ; i <<= 2) { | 681 | if (e_src->status & PCI_ERR_ROOT_COR_RCV) { |
788 | if (i > 4) | 682 | e_info->id = ERR_COR_ID(e_src->id); |
789 | break; | 683 | e_info->severity = AER_CORRECTABLE; |
790 | if (!(e_src->status & i)) | 684 | |
791 | continue; | 685 | if (e_src->status & PCI_ERR_ROOT_MULTI_COR_RCV) |
792 | |||
793 | memset(e_info, 0, sizeof(struct aer_err_info)); | ||
794 | |||
795 | /* Init comprehensive error information */ | ||
796 | if (i & PCI_ERR_ROOT_COR_RCV) { | ||
797 | e_info->id = ERR_COR_ID(e_src->id); | ||
798 | e_info->severity = AER_CORRECTABLE; | ||
799 | } else { | ||
800 | e_info->id = ERR_UNCOR_ID(e_src->id); | ||
801 | e_info->severity = ((e_src->status >> 6) & 1); | ||
802 | } | ||
803 | if (e_src->status & | ||
804 | (PCI_ERR_ROOT_MULTI_COR_RCV | | ||
805 | PCI_ERR_ROOT_MULTI_UNCOR_RCV)) | ||
806 | e_info->multi_error_valid = 1; | 686 | e_info->multi_error_valid = 1; |
687 | else | ||
688 | e_info->multi_error_valid = 0; | ||
689 | |||
690 | aer_print_port_info(p_device->port, e_info); | ||
691 | |||
692 | if (find_source_device(p_device->port, e_info)) | ||
693 | aer_process_err_devices(p_device, e_info); | ||
694 | } | ||
695 | |||
696 | if (e_src->status & PCI_ERR_ROOT_UNCOR_RCV) { | ||
697 | e_info->id = ERR_UNCOR_ID(e_src->id); | ||
698 | |||
699 | if (e_src->status & PCI_ERR_ROOT_FATAL_RCV) | ||
700 | e_info->severity = AER_FATAL; | ||
701 | else | ||
702 | e_info->severity = AER_NONFATAL; | ||
703 | |||
704 | if (e_src->status & PCI_ERR_ROOT_MULTI_UNCOR_RCV) | ||
705 | e_info->multi_error_valid = 1; | ||
706 | else | ||
707 | e_info->multi_error_valid = 0; | ||
807 | 708 | ||
808 | aer_print_port_info(p_device->port, e_info); | 709 | aer_print_port_info(p_device->port, e_info); |
809 | 710 | ||
810 | find_source_device(p_device->port, e_info); | 711 | if (find_source_device(p_device->port, e_info)) |
811 | aer_process_err_devices(p_device, e_info); | 712 | aer_process_err_devices(p_device, e_info); |
812 | } | 713 | } |
813 | 714 | ||
814 | kfree(e_info); | 715 | kfree(e_info); |
815 | } | 716 | } |
816 | 717 | ||
817 | /** | 718 | /** |
719 | * get_e_source - retrieve an error source | ||
720 | * @rpc: pointer to the root port which holds an error | ||
721 | * @e_src: pointer to store retrieved error source | ||
722 | * | ||
723 | * Return 1 if an error source is retrieved, otherwise 0. | ||
724 | * | ||
725 | * Invoked by DPC handler to consume an error. | ||
726 | */ | ||
727 | static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src) | ||
728 | { | ||
729 | unsigned long flags; | ||
730 | int ret = 0; | ||
731 | |||
732 | /* Lock access to Root error producer/consumer index */ | ||
733 | spin_lock_irqsave(&rpc->e_lock, flags); | ||
734 | if (rpc->prod_idx != rpc->cons_idx) { | ||
735 | *e_src = rpc->e_sources[rpc->cons_idx]; | ||
736 | rpc->cons_idx++; | ||
737 | if (rpc->cons_idx == AER_ERROR_SOURCES_MAX) | ||
738 | rpc->cons_idx = 0; | ||
739 | ret = 1; | ||
740 | } | ||
741 | spin_unlock_irqrestore(&rpc->e_lock, flags); | ||
742 | |||
743 | return ret; | ||
744 | } | ||
745 | |||
746 | /** | ||
818 | * aer_isr - consume errors detected by root port | 747 | * aer_isr - consume errors detected by root port |
819 | * @work: definition of this work item | 748 | * @work: definition of this work item |
820 | * | 749 | * |
@@ -824,34 +753,17 @@ void aer_isr(struct work_struct *work) | |||
824 | { | 753 | { |
825 | struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler); | 754 | struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler); |
826 | struct pcie_device *p_device = rpc->rpd; | 755 | struct pcie_device *p_device = rpc->rpd; |
827 | struct aer_err_source *e_src; | 756 | struct aer_err_source e_src; |
828 | 757 | ||
829 | mutex_lock(&rpc->rpc_mutex); | 758 | mutex_lock(&rpc->rpc_mutex); |
830 | e_src = get_e_source(rpc); | 759 | while (get_e_source(rpc, &e_src)) |
831 | while (e_src) { | 760 | aer_isr_one_error(p_device, &e_src); |
832 | aer_isr_one_error(p_device, e_src); | ||
833 | e_src = get_e_source(rpc); | ||
834 | } | ||
835 | mutex_unlock(&rpc->rpc_mutex); | 761 | mutex_unlock(&rpc->rpc_mutex); |
836 | 762 | ||
837 | wake_up(&rpc->wait_release); | 763 | wake_up(&rpc->wait_release); |
838 | } | 764 | } |
839 | 765 | ||
840 | /** | 766 | /** |
841 | * aer_delete_rootport - disable root port aer and delete service data | ||
842 | * @rpc: pointer to a root port device being deleted | ||
843 | * | ||
844 | * Invoked when AER service unloaded on a specific Root Port | ||
845 | */ | ||
846 | void aer_delete_rootport(struct aer_rpc *rpc) | ||
847 | { | ||
848 | /* Disable root port AER itself */ | ||
849 | disable_root_aer(rpc); | ||
850 | |||
851 | kfree(rpc); | ||
852 | } | ||
853 | |||
854 | /** | ||
855 | * aer_init - provide AER initialization | 767 | * aer_init - provide AER initialization |
856 | * @dev: pointer to AER pcie device | 768 | * @dev: pointer to AER pcie device |
857 | * | 769 | * |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 27c0e6eb7136..b7512cf08c58 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -2127,6 +2127,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9602, quirk_disable_msi); | |||
2127 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASUSTEK, 0x9602, quirk_disable_msi); | 2127 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASUSTEK, 0x9602, quirk_disable_msi); |
2128 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AI, 0x9602, quirk_disable_msi); | 2128 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AI, 0x9602, quirk_disable_msi); |
2129 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0xa238, quirk_disable_msi); | 2129 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0xa238, quirk_disable_msi); |
2130 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x5a3f, quirk_disable_msi); | ||
2130 | 2131 | ||
2131 | /* Go through the list of Hypertransport capabilities and | 2132 | /* Go through the list of Hypertransport capabilities and |
2132 | * return 1 if a HT MSI capability is found and enabled */ | 2133 | * return 1 if a HT MSI capability is found and enabled */ |
@@ -2218,15 +2219,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, | |||
2218 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, | 2219 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, |
2219 | ht_enable_msi_mapping); | 2220 | ht_enable_msi_mapping); |
2220 | 2221 | ||
2221 | /* The P5N32-SLI Premium motherboard from Asus has a problem with msi | 2222 | /* The P5N32-SLI motherboards from Asus have a problem with msi |
2222 | * for the MCP55 NIC. It is not yet determined whether the msi problem | 2223 | * for the MCP55 NIC. It is not yet determined whether the msi problem |
2223 | * also affects other devices. As for now, turn off msi for this device. | 2224 | * also affects other devices. As for now, turn off msi for this device. |
2224 | */ | 2225 | */ |
2225 | static void __devinit nvenet_msi_disable(struct pci_dev *dev) | 2226 | static void __devinit nvenet_msi_disable(struct pci_dev *dev) |
2226 | { | 2227 | { |
2227 | if (dmi_name_in_vendors("P5N32-SLI PREMIUM")) { | 2228 | if (dmi_name_in_vendors("P5N32-SLI PREMIUM") || |
2229 | dmi_name_in_vendors("P5N32-E SLI")) { | ||
2228 | dev_info(&dev->dev, | 2230 | dev_info(&dev->dev, |
2229 | "Disabling msi for MCP55 NIC on P5N32-SLI Premium\n"); | 2231 | "Disabling msi for MCP55 NIC on P5N32-SLI\n"); |
2230 | dev->no_msi = 1; | 2232 | dev->no_msi = 1; |
2231 | } | 2233 | } |
2232 | } | 2234 | } |
@@ -2552,6 +2554,19 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov); | |||
2552 | 2554 | ||
2553 | #endif /* CONFIG_PCI_IOV */ | 2555 | #endif /* CONFIG_PCI_IOV */ |
2554 | 2556 | ||
2557 | /* Allow manual resource allocation for PCI hotplug bridges | ||
2558 | * via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For | ||
2559 | * some PCI-PCI hotplug bridges, like PLX 6254 (former HINT HB6), | ||
2560 | * kernel fails to allocate resources when hotplug device is | ||
2561 | * inserted and PCI bus is rescanned. | ||
2562 | */ | ||
2563 | static void __devinit quirk_hotplug_bridge(struct pci_dev *dev) | ||
2564 | { | ||
2565 | dev->is_hotplug_bridge = 1; | ||
2566 | } | ||
2567 | |||
2568 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HINT, 0x0020, quirk_hotplug_bridge); | ||
2569 | |||
2555 | /* | 2570 | /* |
2556 | * This is a quirk for the Ricoh MMC controller found as a part of | 2571 | * This is a quirk for the Ricoh MMC controller found as a part of |
2557 | * some mulifunction chips. | 2572 | * some mulifunction chips. |
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 4fe36d2e1049..19b111383f62 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -838,65 +838,11 @@ static void pci_bus_dump_resources(struct pci_bus *bus) | |||
838 | } | 838 | } |
839 | } | 839 | } |
840 | 840 | ||
841 | static int __init pci_bus_get_depth(struct pci_bus *bus) | ||
842 | { | ||
843 | int depth = 0; | ||
844 | struct pci_dev *dev; | ||
845 | |||
846 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
847 | int ret; | ||
848 | struct pci_bus *b = dev->subordinate; | ||
849 | if (!b) | ||
850 | continue; | ||
851 | |||
852 | ret = pci_bus_get_depth(b); | ||
853 | if (ret + 1 > depth) | ||
854 | depth = ret + 1; | ||
855 | } | ||
856 | |||
857 | return depth; | ||
858 | } | ||
859 | static int __init pci_get_max_depth(void) | ||
860 | { | ||
861 | int depth = 0; | ||
862 | struct pci_bus *bus; | ||
863 | |||
864 | list_for_each_entry(bus, &pci_root_buses, node) { | ||
865 | int ret; | ||
866 | |||
867 | ret = pci_bus_get_depth(bus); | ||
868 | if (ret > depth) | ||
869 | depth = ret; | ||
870 | } | ||
871 | |||
872 | return depth; | ||
873 | } | ||
874 | |||
875 | /* | ||
876 | * first try will not touch pci bridge res | ||
877 | * second and later try will clear small leaf bridge res | ||
878 | * will stop till to the max deepth if can not find good one | ||
879 | */ | ||
880 | void __init | 841 | void __init |
881 | pci_assign_unassigned_resources(void) | 842 | pci_assign_unassigned_resources(void) |
882 | { | 843 | { |
883 | struct pci_bus *bus; | 844 | struct pci_bus *bus; |
884 | int tried_times = 0; | ||
885 | enum release_type rel_type = leaf_only; | ||
886 | struct resource_list_x head, *list; | ||
887 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
888 | IORESOURCE_PREFETCH; | ||
889 | unsigned long failed_type; | ||
890 | int max_depth = pci_get_max_depth(); | ||
891 | int pci_try_num; | ||
892 | 845 | ||
893 | head.next = NULL; | ||
894 | |||
895 | pci_try_num = max_depth + 1; | ||
896 | printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", | ||
897 | max_depth, pci_try_num); | ||
898 | |||
899 | again: | ||
900 | /* Depth first, calculate sizes and alignments of all | 846 | /* Depth first, calculate sizes and alignments of all |
901 | subordinate buses. */ | 847 | subordinate buses. */ |
902 | list_for_each_entry(bus, &pci_root_buses, node) { | 848 | list_for_each_entry(bus, &pci_root_buses, node) { |
@@ -904,65 +850,9 @@ again: | |||
904 | } | 850 | } |
905 | /* Depth last, allocate resources and update the hardware. */ | 851 | /* Depth last, allocate resources and update the hardware. */ |
906 | list_for_each_entry(bus, &pci_root_buses, node) { | 852 | list_for_each_entry(bus, &pci_root_buses, node) { |
907 | __pci_bus_assign_resources(bus, &head); | 853 | pci_bus_assign_resources(bus); |
908 | } | ||
909 | tried_times++; | ||
910 | |||
911 | /* any device complain? */ | ||
912 | if (!head.next) | ||
913 | goto enable_and_dump; | ||
914 | failed_type = 0; | ||
915 | for (list = head.next; list;) { | ||
916 | failed_type |= list->flags; | ||
917 | list = list->next; | ||
918 | } | ||
919 | /* | ||
920 | * io port are tight, don't try extra | ||
921 | * or if reach the limit, don't want to try more | ||
922 | */ | ||
923 | failed_type &= type_mask; | ||
924 | if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) { | ||
925 | free_failed_list(&head); | ||
926 | goto enable_and_dump; | ||
927 | } | ||
928 | |||
929 | printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", | ||
930 | tried_times + 1); | ||
931 | |||
932 | /* third times and later will not check if it is leaf */ | ||
933 | if ((tried_times + 1) > 2) | ||
934 | rel_type = whole_subtree; | ||
935 | |||
936 | /* | ||
937 | * Try to release leaf bridge's resources that doesn't fit resource of | ||
938 | * child device under that bridge | ||
939 | */ | ||
940 | for (list = head.next; list;) { | ||
941 | bus = list->dev->bus; | ||
942 | pci_bus_release_bridge_resources(bus, list->flags & type_mask, | ||
943 | rel_type); | ||
944 | list = list->next; | ||
945 | } | ||
946 | /* restore size and flags */ | ||
947 | for (list = head.next; list;) { | ||
948 | struct resource *res = list->res; | ||
949 | |||
950 | res->start = list->start; | ||
951 | res->end = list->end; | ||
952 | res->flags = list->flags; | ||
953 | if (list->dev->subordinate) | ||
954 | res->flags = 0; | ||
955 | |||
956 | list = list->next; | ||
957 | } | ||
958 | free_failed_list(&head); | ||
959 | |||
960 | goto again; | ||
961 | |||
962 | enable_and_dump: | ||
963 | /* Depth last, update the hardware. */ | ||
964 | list_for_each_entry(bus, &pci_root_buses, node) | ||
965 | pci_enable_bridges(bus); | 854 | pci_enable_bridges(bus); |
855 | } | ||
966 | 856 | ||
967 | /* dump the resource on buses */ | 857 | /* dump the resource on buses */ |
968 | list_for_each_entry(bus, &pci_root_buses, node) { | 858 | list_for_each_entry(bus, &pci_root_buses, node) { |
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 659eaa0fc48f..e0189cf7c558 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c | |||
@@ -97,6 +97,50 @@ static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf) | |||
97 | return bus_speed_read(slot->bus->cur_bus_speed, buf); | 97 | return bus_speed_read(slot->bus->cur_bus_speed, buf); |
98 | } | 98 | } |
99 | 99 | ||
100 | static void remove_sysfs_files(struct pci_slot *slot) | ||
101 | { | ||
102 | char func[10]; | ||
103 | struct list_head *tmp; | ||
104 | |||
105 | list_for_each(tmp, &slot->bus->devices) { | ||
106 | struct pci_dev *dev = pci_dev_b(tmp); | ||
107 | if (PCI_SLOT(dev->devfn) != slot->number) | ||
108 | continue; | ||
109 | sysfs_remove_link(&dev->dev.kobj, "slot"); | ||
110 | |||
111 | snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn)); | ||
112 | sysfs_remove_link(&slot->kobj, func); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | static int create_sysfs_files(struct pci_slot *slot) | ||
117 | { | ||
118 | int result; | ||
119 | char func[10]; | ||
120 | struct list_head *tmp; | ||
121 | |||
122 | list_for_each(tmp, &slot->bus->devices) { | ||
123 | struct pci_dev *dev = pci_dev_b(tmp); | ||
124 | if (PCI_SLOT(dev->devfn) != slot->number) | ||
125 | continue; | ||
126 | |||
127 | result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot"); | ||
128 | if (result) | ||
129 | goto fail; | ||
130 | |||
131 | snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn)); | ||
132 | result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func); | ||
133 | if (result) | ||
134 | goto fail; | ||
135 | } | ||
136 | |||
137 | return 0; | ||
138 | |||
139 | fail: | ||
140 | remove_sysfs_files(slot); | ||
141 | return result; | ||
142 | } | ||
143 | |||
100 | static void pci_slot_release(struct kobject *kobj) | 144 | static void pci_slot_release(struct kobject *kobj) |
101 | { | 145 | { |
102 | struct pci_dev *dev; | 146 | struct pci_dev *dev; |
@@ -109,6 +153,8 @@ static void pci_slot_release(struct kobject *kobj) | |||
109 | if (PCI_SLOT(dev->devfn) == slot->number) | 153 | if (PCI_SLOT(dev->devfn) == slot->number) |
110 | dev->slot = NULL; | 154 | dev->slot = NULL; |
111 | 155 | ||
156 | remove_sysfs_files(slot); | ||
157 | |||
112 | list_del(&slot->list); | 158 | list_del(&slot->list); |
113 | 159 | ||
114 | kfree(slot); | 160 | kfree(slot); |
@@ -300,6 +346,8 @@ placeholder: | |||
300 | INIT_LIST_HEAD(&slot->list); | 346 | INIT_LIST_HEAD(&slot->list); |
301 | list_add(&slot->list, &parent->slots); | 347 | list_add(&slot->list, &parent->slots); |
302 | 348 | ||
349 | create_sysfs_files(slot); | ||
350 | |||
303 | list_for_each_entry(dev, &parent->devices, bus_list) | 351 | list_for_each_entry(dev, &parent->devices, bus_list) |
304 | if (PCI_SLOT(dev->devfn) == slot_nr) | 352 | if (PCI_SLOT(dev->devfn) == slot_nr) |
305 | dev->slot = slot; | 353 | dev->slot = slot; |