diff options
author | Jiri Kosina <jkosina@suse.cz> | 2010-12-22 12:57:02 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2010-12-22 12:57:02 -0500 |
commit | 4b7bd364700d9ac8372eff48832062b936d0793b (patch) | |
tree | 0dbf78c95456a0b02d07fcd473281f04a87e266d /drivers/pci | |
parent | c0d8768af260e2cbb4bf659ae6094a262c86b085 (diff) | |
parent | 90a8a73c06cc32b609a880d48449d7083327e11a (diff) |
Merge branch 'master' into for-next
Conflicts:
MAINTAINERS
arch/arm/mach-omap2/pm24xx.c
drivers/scsi/bfa/bfa_fcpim.c
Needed to update to apply fixes for which the old branch was too
outdated.
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/Makefile | 1 | ||||
-rw-r--r-- | drivers/pci/bus.c | 53 | ||||
-rw-r--r-- | drivers/pci/dmar.c | 5 | ||||
-rw-r--r-- | drivers/pci/hotplug/ibmphp_ebda.c | 6 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 23 | ||||
-rw-r--r-- | drivers/pci/pci.c | 12 | ||||
-rw-r--r-- | drivers/pci/pci.h | 7 | ||||
-rw-r--r-- | drivers/pci/proc.c | 3 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 44 | ||||
-rw-r--r-- | drivers/pci/xen-pcifront.c | 6 |
10 files changed, 100 insertions, 60 deletions
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index f01e344cf4bd..98e6fdf34d30 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile | |||
@@ -49,6 +49,7 @@ obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o | |||
49 | obj-$(CONFIG_X86_VISWS) += setup-irq.o | 49 | obj-$(CONFIG_X86_VISWS) += setup-irq.o |
50 | obj-$(CONFIG_MN10300) += setup-bus.o | 50 | obj-$(CONFIG_MN10300) += setup-bus.o |
51 | obj-$(CONFIG_MICROBLAZE) += setup-bus.o | 51 | obj-$(CONFIG_MICROBLAZE) += setup-bus.o |
52 | obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o | ||
52 | 53 | ||
53 | # | 54 | # |
54 | # ACPI Related PCI FW Functions | 55 | # ACPI Related PCI FW Functions |
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 5624db8c9ad0..69546e9213dd 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c | |||
@@ -64,49 +64,6 @@ void pci_bus_remove_resources(struct pci_bus *bus) | |||
64 | } | 64 | } |
65 | } | 65 | } |
66 | 66 | ||
67 | /* | ||
68 | * Find the highest-address bus resource below the cursor "res". If the | ||
69 | * cursor is NULL, return the highest resource. | ||
70 | */ | ||
71 | static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus, | ||
72 | unsigned int type, | ||
73 | struct resource *res) | ||
74 | { | ||
75 | struct resource *r, *prev = NULL; | ||
76 | int i; | ||
77 | |||
78 | pci_bus_for_each_resource(bus, r, i) { | ||
79 | if (!r) | ||
80 | continue; | ||
81 | |||
82 | if ((r->flags & IORESOURCE_TYPE_BITS) != type) | ||
83 | continue; | ||
84 | |||
85 | /* If this resource is at or past the cursor, skip it */ | ||
86 | if (res) { | ||
87 | if (r == res) | ||
88 | continue; | ||
89 | if (r->end > res->end) | ||
90 | continue; | ||
91 | if (r->end == res->end && r->start > res->start) | ||
92 | continue; | ||
93 | } | ||
94 | |||
95 | if (!prev) | ||
96 | prev = r; | ||
97 | |||
98 | /* | ||
99 | * A small resource is higher than a large one that ends at | ||
100 | * the same address. | ||
101 | */ | ||
102 | if (r->end > prev->end || | ||
103 | (r->end == prev->end && r->start > prev->start)) | ||
104 | prev = r; | ||
105 | } | ||
106 | |||
107 | return prev; | ||
108 | } | ||
109 | |||
110 | /** | 67 | /** |
111 | * pci_bus_alloc_resource - allocate a resource from a parent bus | 68 | * pci_bus_alloc_resource - allocate a resource from a parent bus |
112 | * @bus: PCI bus | 69 | * @bus: PCI bus |
@@ -132,10 +89,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | |||
132 | resource_size_t), | 89 | resource_size_t), |
133 | void *alignf_data) | 90 | void *alignf_data) |
134 | { | 91 | { |
135 | int ret = -ENOMEM; | 92 | int i, ret = -ENOMEM; |
136 | struct resource *r; | 93 | struct resource *r; |
137 | resource_size_t max = -1; | 94 | resource_size_t max = -1; |
138 | unsigned int type = res->flags & IORESOURCE_TYPE_BITS; | ||
139 | 95 | ||
140 | type_mask |= IORESOURCE_IO | IORESOURCE_MEM; | 96 | type_mask |= IORESOURCE_IO | IORESOURCE_MEM; |
141 | 97 | ||
@@ -143,9 +99,10 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, | |||
143 | if (!(res->flags & IORESOURCE_MEM_64)) | 99 | if (!(res->flags & IORESOURCE_MEM_64)) |
144 | max = PCIBIOS_MAX_MEM_32; | 100 | max = PCIBIOS_MAX_MEM_32; |
145 | 101 | ||
146 | /* Look for space at highest addresses first */ | 102 | pci_bus_for_each_resource(bus, r, i) { |
147 | r = pci_bus_find_resource_prev(bus, type, NULL); | 103 | if (!r) |
148 | for ( ; r; r = pci_bus_find_resource_prev(bus, type, r)) { | 104 | continue; |
105 | |||
149 | /* type_mask must match */ | 106 | /* type_mask must match */ |
150 | if ((res->flags ^ r->flags) & type_mask) | 107 | if ((res->flags ^ r->flags) & type_mask) |
151 | continue; | 108 | continue; |
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 0157708d474d..09933eb9126b 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -1417,6 +1417,11 @@ int __init enable_drhd_fault_handling(void) | |||
1417 | (unsigned long long)drhd->reg_base_addr, ret); | 1417 | (unsigned long long)drhd->reg_base_addr, ret); |
1418 | return -1; | 1418 | return -1; |
1419 | } | 1419 | } |
1420 | |||
1421 | /* | ||
1422 | * Clear any previous faults. | ||
1423 | */ | ||
1424 | dmar_fault(iommu->irq, iommu); | ||
1420 | } | 1425 | } |
1421 | 1426 | ||
1422 | return 0; | 1427 | return 0; |
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index 5becbdee4027..2850e64dedae 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c | |||
@@ -276,6 +276,12 @@ int __init ibmphp_access_ebda (void) | |||
276 | 276 | ||
277 | for (;;) { | 277 | for (;;) { |
278 | offset = next_offset; | 278 | offset = next_offset; |
279 | |||
280 | /* Make sure what we read is still in the mapped section */ | ||
281 | if (WARN(offset > (ebda_sz * 1024 - 4), | ||
282 | "ibmphp_ebda: next read is beyond ebda_sz\n")) | ||
283 | break; | ||
284 | |||
279 | next_offset = readw (io_mem + offset); /* offset of next blk */ | 285 | next_offset = readw (io_mem + offset); /* offset of next blk */ |
280 | 286 | ||
281 | offset += 2; | 287 | offset += 2; |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index b5a7d9bfcb24..63d5042f2079 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -705,17 +705,21 @@ void pci_remove_legacy_files(struct pci_bus *b) | |||
705 | 705 | ||
706 | #ifdef HAVE_PCI_MMAP | 706 | #ifdef HAVE_PCI_MMAP |
707 | 707 | ||
708 | int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma) | 708 | int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma, |
709 | enum pci_mmap_api mmap_api) | ||
709 | { | 710 | { |
710 | unsigned long nr, start, size; | 711 | unsigned long nr, start, size, pci_start; |
711 | 712 | ||
713 | if (pci_resource_len(pdev, resno) == 0) | ||
714 | return 0; | ||
712 | nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | 715 | nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; |
713 | start = vma->vm_pgoff; | 716 | start = vma->vm_pgoff; |
714 | size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; | 717 | size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; |
715 | if (start < size && size - start >= nr) | 718 | pci_start = (mmap_api == PCI_MMAP_PROCFS) ? |
719 | pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0; | ||
720 | if (start >= pci_start && start < pci_start + size && | ||
721 | start + nr <= pci_start + size) | ||
716 | return 1; | 722 | return 1; |
717 | WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n", | ||
718 | current->comm, start, start+nr, pci_name(pdev), resno, size); | ||
719 | return 0; | 723 | return 0; |
720 | } | 724 | } |
721 | 725 | ||
@@ -745,8 +749,15 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, | |||
745 | if (i >= PCI_ROM_RESOURCE) | 749 | if (i >= PCI_ROM_RESOURCE) |
746 | return -ENODEV; | 750 | return -ENODEV; |
747 | 751 | ||
748 | if (!pci_mmap_fits(pdev, i, vma)) | 752 | if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) { |
753 | WARN(1, "process \"%s\" tried to map 0x%08lx bytes " | ||
754 | "at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n", | ||
755 | current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff, | ||
756 | pci_name(pdev), i, | ||
757 | (u64)pci_resource_start(pdev, i), | ||
758 | (u64)pci_resource_len(pdev, i)); | ||
749 | return -EINVAL; | 759 | return -EINVAL; |
760 | } | ||
750 | 761 | ||
751 | /* pci_mmap_page_range() expects the same kind of entry as coming | 762 | /* pci_mmap_page_range() expects the same kind of entry as coming |
752 | * from /proc/bus/pci/ which is a "user visible" value. If this is | 763 | * from /proc/bus/pci/ which is a "user visible" value. If this is |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e98c8104297b..710c8a29be0d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -1007,6 +1007,18 @@ static int __pci_enable_device_flags(struct pci_dev *dev, | |||
1007 | int err; | 1007 | int err; |
1008 | int i, bars = 0; | 1008 | int i, bars = 0; |
1009 | 1009 | ||
1010 | /* | ||
1011 | * Power state could be unknown at this point, either due to a fresh | ||
1012 | * boot or a device removal call. So get the current power state | ||
1013 | * so that things like MSI message writing will behave as expected | ||
1014 | * (e.g. if the device really is in D0 at enable time). | ||
1015 | */ | ||
1016 | if (dev->pm_cap) { | ||
1017 | u16 pmcsr; | ||
1018 | pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); | ||
1019 | dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK); | ||
1020 | } | ||
1021 | |||
1010 | if (atomic_add_return(1, &dev->enable_cnt) > 1) | 1022 | if (atomic_add_return(1, &dev->enable_cnt) > 1) |
1011 | return 0; /* already enabled */ | 1023 | return 0; /* already enabled */ |
1012 | 1024 | ||
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index f5c7c382765f..7d33f6673868 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -22,8 +22,13 @@ extern void pci_remove_firmware_label_files(struct pci_dev *pdev); | |||
22 | #endif | 22 | #endif |
23 | extern void pci_cleanup_rom(struct pci_dev *dev); | 23 | extern void pci_cleanup_rom(struct pci_dev *dev); |
24 | #ifdef HAVE_PCI_MMAP | 24 | #ifdef HAVE_PCI_MMAP |
25 | enum pci_mmap_api { | ||
26 | PCI_MMAP_SYSFS, /* mmap on /sys/bus/pci/devices/<BDF>/resource<N> */ | ||
27 | PCI_MMAP_PROCFS /* mmap on /proc/bus/pci/<BDF> */ | ||
28 | }; | ||
25 | extern int pci_mmap_fits(struct pci_dev *pdev, int resno, | 29 | extern int pci_mmap_fits(struct pci_dev *pdev, int resno, |
26 | struct vm_area_struct *vma); | 30 | struct vm_area_struct *vmai, |
31 | enum pci_mmap_api mmap_api); | ||
27 | #endif | 32 | #endif |
28 | int pci_probe_reset_function(struct pci_dev *dev); | 33 | int pci_probe_reset_function(struct pci_dev *dev); |
29 | 34 | ||
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 297b72c880a1..27911b55c2a5 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/proc_fs.h> | 11 | #include <linux/proc_fs.h> |
12 | #include <linux/seq_file.h> | 12 | #include <linux/seq_file.h> |
13 | #include <linux/smp_lock.h> | ||
14 | #include <linux/capability.h> | 13 | #include <linux/capability.h> |
15 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
16 | #include <asm/byteorder.h> | 15 | #include <asm/byteorder.h> |
@@ -257,7 +256,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) | |||
257 | 256 | ||
258 | /* Make sure the caller is mapping a real resource for this device */ | 257 | /* Make sure the caller is mapping a real resource for this device */ |
259 | for (i = 0; i < PCI_ROM_RESOURCE; i++) { | 258 | for (i = 0; i < PCI_ROM_RESOURCE; i++) { |
260 | if (pci_mmap_fits(dev, i, vma)) | 259 | if (pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS)) |
261 | break; | 260 | break; |
262 | } | 261 | } |
263 | 262 | ||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f5c63fe9db5c..53a786fd0d40 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -2136,6 +2136,24 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB, | |||
2136 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB, | 2136 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB, |
2137 | quirk_unhide_mch_dev6); | 2137 | quirk_unhide_mch_dev6); |
2138 | 2138 | ||
2139 | #ifdef CONFIG_TILE | ||
2140 | /* | ||
2141 | * The Tilera TILEmpower platform needs to set the link speed | ||
2142 | * to 2.5GT(Giga-Transfers)/s (Gen 1). The default link speed | ||
2143 | * setting is 5GT/s (Gen 2). 0x98 is the Link Control2 PCIe | ||
2144 | * capability register of the PEX8624 PCIe switch. The switch | ||
2145 | * supports link speed auto negotiation, but falsely sets | ||
2146 | * the link speed to 5GT/s. | ||
2147 | */ | ||
2148 | static void __devinit quirk_tile_plx_gen1(struct pci_dev *dev) | ||
2149 | { | ||
2150 | if (tile_plx_gen1) { | ||
2151 | pci_write_config_dword(dev, 0x98, 0x1); | ||
2152 | mdelay(50); | ||
2153 | } | ||
2154 | } | ||
2155 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1); | ||
2156 | #endif /* CONFIG_TILE */ | ||
2139 | 2157 | ||
2140 | #ifdef CONFIG_PCI_MSI | 2158 | #ifdef CONFIG_PCI_MSI |
2141 | /* Some chipsets do not support MSI. We cannot easily rely on setting | 2159 | /* Some chipsets do not support MSI. We cannot easily rely on setting |
@@ -2311,6 +2329,9 @@ static void __devinit nvbridge_check_legacy_irq_routing(struct pci_dev *dev) | |||
2311 | { | 2329 | { |
2312 | u32 cfg; | 2330 | u32 cfg; |
2313 | 2331 | ||
2332 | if (!pci_find_capability(dev, PCI_CAP_ID_HT)) | ||
2333 | return; | ||
2334 | |||
2314 | pci_read_config_dword(dev, 0x74, &cfg); | 2335 | pci_read_config_dword(dev, 0x74, &cfg); |
2315 | 2336 | ||
2316 | if (cfg & ((1 << 2) | (1 << 15))) { | 2337 | if (cfg & ((1 << 2) | (1 << 15))) { |
@@ -2746,6 +2767,29 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_m | |||
2746 | DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); | 2767 | DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); |
2747 | #endif /*CONFIG_MMC_RICOH_MMC*/ | 2768 | #endif /*CONFIG_MMC_RICOH_MMC*/ |
2748 | 2769 | ||
2770 | #if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP) | ||
2771 | #define VTUNCERRMSK_REG 0x1ac | ||
2772 | #define VTD_MSK_SPEC_ERRORS (1 << 31) | ||
2773 | /* | ||
2774 | * This is a quirk for masking vt-d spec defined errors to platform error | ||
2775 | * handling logic. With out this, platforms using Intel 7500, 5500 chipsets | ||
2776 | * (and the derivative chipsets like X58 etc) seem to generate NMI/SMI (based | ||
2777 | * on the RAS config settings of the platform) when a vt-d fault happens. | ||
2778 | * The resulting SMI caused the system to hang. | ||
2779 | * | ||
2780 | * VT-d spec related errors are already handled by the VT-d OS code, so no | ||
2781 | * need to report the same error through other channels. | ||
2782 | */ | ||
2783 | static void vtd_mask_spec_errors(struct pci_dev *dev) | ||
2784 | { | ||
2785 | u32 word; | ||
2786 | |||
2787 | pci_read_config_dword(dev, VTUNCERRMSK_REG, &word); | ||
2788 | pci_write_config_dword(dev, VTUNCERRMSK_REG, word | VTD_MSK_SPEC_ERRORS); | ||
2789 | } | ||
2790 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors); | ||
2791 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors); | ||
2792 | #endif | ||
2749 | 2793 | ||
2750 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, | 2794 | static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, |
2751 | struct pci_fixup *end) | 2795 | struct pci_fixup *end) |
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index a87c4985326e..3a5a6fcc0ead 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
15 | #include <linux/msi.h> | 15 | #include <linux/msi.h> |
16 | #include <xen/xenbus.h> | ||
17 | #include <xen/interface/io/pciif.h> | 16 | #include <xen/interface/io/pciif.h> |
18 | #include <asm/xen/pci.h> | 17 | #include <asm/xen/pci.h> |
19 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
@@ -576,8 +575,9 @@ static pci_ers_result_t pcifront_common_process(int cmd, | |||
576 | 575 | ||
577 | pcidev = pci_get_bus_and_slot(bus, devfn); | 576 | pcidev = pci_get_bus_and_slot(bus, devfn); |
578 | if (!pcidev || !pcidev->driver) { | 577 | if (!pcidev || !pcidev->driver) { |
579 | dev_err(&pcidev->dev, | 578 | dev_err(&pdev->xdev->dev, "device or AER driver is NULL\n"); |
580 | "device or driver is NULL\n"); | 579 | if (pcidev) |
580 | pci_dev_put(pcidev); | ||
581 | return result; | 581 | return result; |
582 | } | 582 | } |
583 | pdrv = pcidev->driver; | 583 | pdrv = pcidev->driver; |