diff options
Diffstat (limited to 'arch/x86/pci/acpi.c')
-rw-r--r-- | arch/x86/pci/acpi.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 6e22454bfaa6..c7b1ebfb7da7 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <linux/init.h> | 3 | #include <linux/init.h> |
4 | #include <linux/irq.h> | 4 | #include <linux/irq.h> |
5 | #include <linux/dmi.h> | 5 | #include <linux/dmi.h> |
6 | #include <linux/slab.h> | ||
6 | #include <asm/numa.h> | 7 | #include <asm/numa.h> |
7 | #include <asm/pci_x86.h> | 8 | #include <asm/pci_x86.h> |
8 | 9 | ||
@@ -122,8 +123,8 @@ setup_resource(struct acpi_resource *acpi_res, void *data) | |||
122 | struct acpi_resource_address64 addr; | 123 | struct acpi_resource_address64 addr; |
123 | acpi_status status; | 124 | acpi_status status; |
124 | unsigned long flags; | 125 | unsigned long flags; |
125 | struct resource *root; | 126 | struct resource *root, *conflict; |
126 | u64 start, end; | 127 | u64 start, end, max_len; |
127 | 128 | ||
128 | status = resource_to_addr(acpi_res, &addr); | 129 | status = resource_to_addr(acpi_res, &addr); |
129 | if (!ACPI_SUCCESS(status)) | 130 | if (!ACPI_SUCCESS(status)) |
@@ -140,6 +141,17 @@ setup_resource(struct acpi_resource *acpi_res, void *data) | |||
140 | } else | 141 | } else |
141 | return AE_OK; | 142 | return AE_OK; |
142 | 143 | ||
144 | max_len = addr.maximum - addr.minimum + 1; | ||
145 | if (addr.address_length > max_len) { | ||
146 | dev_printk(KERN_DEBUG, &info->bridge->dev, | ||
147 | "host bridge window length %#llx doesn't fit in " | ||
148 | "%#llx-%#llx, trimming\n", | ||
149 | (unsigned long long) addr.address_length, | ||
150 | (unsigned long long) addr.minimum, | ||
151 | (unsigned long long) addr.maximum); | ||
152 | addr.address_length = max_len; | ||
153 | } | ||
154 | |||
143 | start = addr.minimum + addr.translation_offset; | 155 | start = addr.minimum + addr.translation_offset; |
144 | end = start + addr.address_length - 1; | 156 | end = start + addr.address_length - 1; |
145 | 157 | ||
@@ -157,9 +169,12 @@ setup_resource(struct acpi_resource *acpi_res, void *data) | |||
157 | return AE_OK; | 169 | return AE_OK; |
158 | } | 170 | } |
159 | 171 | ||
160 | if (insert_resource(root, res)) { | 172 | conflict = insert_resource_conflict(root, res); |
173 | if (conflict) { | ||
161 | dev_err(&info->bridge->dev, | 174 | dev_err(&info->bridge->dev, |
162 | "can't allocate host bridge window %pR\n", res); | 175 | "address space collision: host bridge window %pR " |
176 | "conflicts with %s %pR\n", | ||
177 | res, conflict->name, conflict); | ||
163 | } else { | 178 | } else { |
164 | pci_bus_add_resource(info->bus, res, 0); | 179 | pci_bus_add_resource(info->bus, res, 0); |
165 | info->res_num++; | 180 | info->res_num++; |