diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:56:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:56:44 -0400 |
commit | 99759619b27662d1290901228d77a293e6e83200 (patch) | |
tree | e76841fa3f59ebfc3975ff40bbc14363d0fdc5d3 /drivers/pci | |
parent | b061c59c27e0385e53c961d9fbd18c1c078d9823 (diff) | |
parent | 65d8defe2e13fbebd74f96d2b5ca9aad435e6648 (diff) |
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6:
PCI: label: remove #include of ACPI header to avoid warnings
PCI: label: Fix compilation error when CONFIG_ACPI is unset
PCI: pre-allocate additional resources to devices only after successful allocation of essential resources.
PCI: introduce reset_resource()
PCI: data structure agnostic free list function
PCI: refactor io size calculation code
PCI: do not create quirk I/O regions below PCIBIOS_MIN_IO for ICH
PCI hotplug: acpiphp: set current_state to D0 in register_slot
PCI: Export ACPI _DSM provided firmware instance number and string name to sysfs
PCI: add more checking to ICH region quirks
PCI: aer-inject: Override PCIe AER Mask Registers
PCI: fix tlan build when CONFIG_PCI is not enabled
PCI: remove quirk for pre-production systems
PCI: Avoid potential NULL pointer dereference in pci_scan_bridge
PCI/lpc: irq and pci_ids patch for Intel DH89xxCC DeviceIDs
PCI: sysfs: Fix failure path for addition of "vpd" attribute
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/Kconfig | 2 | ||||
-rw-r--r-- | drivers/pci/Makefile | 3 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 1 | ||||
-rw-r--r-- | drivers/pci/pci-label.c | 252 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 2 | ||||
-rw-r--r-- | drivers/pci/pci.h | 2 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aer_inject.c | 31 | ||||
-rw-r--r-- | drivers/pci/probe.c | 4 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 113 | ||||
-rw-r--r-- | drivers/pci/setup-bus.c | 321 |
10 files changed, 576 insertions, 155 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index a9523fdc6911..c8ff646c0b05 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig | |||
@@ -87,3 +87,5 @@ config PCI_IOAPIC | |||
87 | depends on ACPI | 87 | depends on ACPI |
88 | depends on HOTPLUG | 88 | depends on HOTPLUG |
89 | default y | 89 | default y |
90 | |||
91 | select NLS if (DMI || ACPI) | ||
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 77cf813ba264..98d61c8e984b 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile | |||
@@ -54,8 +54,9 @@ obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o | |||
54 | 54 | ||
55 | # | 55 | # |
56 | # ACPI Related PCI FW Functions | 56 | # ACPI Related PCI FW Functions |
57 | # ACPI _DSM provided firmware instance and string name | ||
57 | # | 58 | # |
58 | obj-$(CONFIG_ACPI) += pci-acpi.o | 59 | obj-$(CONFIG_ACPI) += pci-acpi.o pci-label.o |
59 | 60 | ||
60 | # SMBIOS provided firmware instance and labels | 61 | # SMBIOS provided firmware instance and labels |
61 | obj-$(CONFIG_DMI) += pci-label.o | 62 | obj-$(CONFIG_DMI) += pci-label.o |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index cb23aa2ebf96..e610cfe4f07b 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -212,6 +212,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
212 | 212 | ||
213 | pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); | 213 | pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); |
214 | if (pdev) { | 214 | if (pdev) { |
215 | pdev->current_state = PCI_D0; | ||
215 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); | 216 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); |
216 | pci_dev_put(pdev); | 217 | pci_dev_put(pdev); |
217 | } | 218 | } |
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c index 90c0a729cd3a..77cb2a14c896 100644 --- a/drivers/pci/pci-label.c +++ b/drivers/pci/pci-label.c | |||
@@ -5,6 +5,13 @@ | |||
5 | * by Narendra K <Narendra_K@dell.com>, | 5 | * by Narendra K <Narendra_K@dell.com>, |
6 | * Jordan Hargrave <Jordan_Hargrave@dell.com> | 6 | * Jordan Hargrave <Jordan_Hargrave@dell.com> |
7 | * | 7 | * |
8 | * PCI Firmware Specification Revision 3.1 section 4.6.7 (DSM for Naming a | ||
9 | * PCI or PCI Express Device Under Operating Systems) defines an instance | ||
10 | * number and string name. This code retrieves them and exports them to sysfs. | ||
11 | * If the system firmware does not provide the ACPI _DSM (Device Specific | ||
12 | * Method), then the SMBIOS type 41 instance number and string is exported to | ||
13 | * sysfs. | ||
14 | * | ||
8 | * SMBIOS defines type 41 for onboard pci devices. This code retrieves | 15 | * SMBIOS defines type 41 for onboard pci devices. This code retrieves |
9 | * the instance number and string from the type 41 record and exports | 16 | * the instance number and string from the type 41 record and exports |
10 | * it to sysfs. | 17 | * it to sysfs. |
@@ -19,8 +26,29 @@ | |||
19 | #include <linux/pci_ids.h> | 26 | #include <linux/pci_ids.h> |
20 | #include <linux/module.h> | 27 | #include <linux/module.h> |
21 | #include <linux/device.h> | 28 | #include <linux/device.h> |
29 | #include <linux/nls.h> | ||
30 | #include <linux/acpi.h> | ||
31 | #include <linux/pci-acpi.h> | ||
32 | #include <acpi/acpi_bus.h> | ||
22 | #include "pci.h" | 33 | #include "pci.h" |
23 | 34 | ||
35 | #define DEVICE_LABEL_DSM 0x07 | ||
36 | |||
37 | #ifndef CONFIG_DMI | ||
38 | |||
39 | static inline int | ||
40 | pci_create_smbiosname_file(struct pci_dev *pdev) | ||
41 | { | ||
42 | return -1; | ||
43 | } | ||
44 | |||
45 | static inline void | ||
46 | pci_remove_smbiosname_file(struct pci_dev *pdev) | ||
47 | { | ||
48 | } | ||
49 | |||
50 | #else | ||
51 | |||
24 | enum smbios_attr_enum { | 52 | enum smbios_attr_enum { |
25 | SMBIOS_ATTR_NONE = 0, | 53 | SMBIOS_ATTR_NONE = 0, |
26 | SMBIOS_ATTR_LABEL_SHOW, | 54 | SMBIOS_ATTR_LABEL_SHOW, |
@@ -120,9 +148,7 @@ static struct attribute_group smbios_attr_group = { | |||
120 | static int | 148 | static int |
121 | pci_create_smbiosname_file(struct pci_dev *pdev) | 149 | pci_create_smbiosname_file(struct pci_dev *pdev) |
122 | { | 150 | { |
123 | if (!sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group)) | 151 | return sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group); |
124 | return 0; | ||
125 | return -ENODEV; | ||
126 | } | 152 | } |
127 | 153 | ||
128 | static void | 154 | static void |
@@ -131,13 +157,227 @@ pci_remove_smbiosname_file(struct pci_dev *pdev) | |||
131 | sysfs_remove_group(&pdev->dev.kobj, &smbios_attr_group); | 157 | sysfs_remove_group(&pdev->dev.kobj, &smbios_attr_group); |
132 | } | 158 | } |
133 | 159 | ||
160 | #endif | ||
161 | |||
162 | #ifndef CONFIG_ACPI | ||
163 | |||
164 | static inline int | ||
165 | pci_create_acpi_index_label_files(struct pci_dev *pdev) | ||
166 | { | ||
167 | return -1; | ||
168 | } | ||
169 | |||
170 | static inline int | ||
171 | pci_remove_acpi_index_label_files(struct pci_dev *pdev) | ||
172 | { | ||
173 | return -1; | ||
174 | } | ||
175 | |||
176 | static inline bool | ||
177 | device_has_dsm(struct device *dev) | ||
178 | { | ||
179 | return false; | ||
180 | } | ||
181 | |||
182 | #else | ||
183 | |||
184 | static const char device_label_dsm_uuid[] = { | ||
185 | 0xD0, 0x37, 0xC9, 0xE5, 0x53, 0x35, 0x7A, 0x4D, | ||
186 | 0x91, 0x17, 0xEA, 0x4D, 0x19, 0xC3, 0x43, 0x4D | ||
187 | }; | ||
188 | |||
189 | enum acpi_attr_enum { | ||
190 | ACPI_ATTR_NONE = 0, | ||
191 | ACPI_ATTR_LABEL_SHOW, | ||
192 | ACPI_ATTR_INDEX_SHOW, | ||
193 | }; | ||
194 | |||
195 | static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf) | ||
196 | { | ||
197 | int len; | ||
198 | len = utf16s_to_utf8s((const wchar_t *)obj-> | ||
199 | package.elements[1].string.pointer, | ||
200 | obj->package.elements[1].string.length, | ||
201 | UTF16_LITTLE_ENDIAN, | ||
202 | buf, PAGE_SIZE); | ||
203 | buf[len] = '\n'; | ||
204 | } | ||
205 | |||
206 | static int | ||
207 | dsm_get_label(acpi_handle handle, int func, | ||
208 | struct acpi_buffer *output, | ||
209 | char *buf, enum acpi_attr_enum attribute) | ||
210 | { | ||
211 | struct acpi_object_list input; | ||
212 | union acpi_object params[4]; | ||
213 | union acpi_object *obj; | ||
214 | int len = 0; | ||
215 | |||
216 | int err; | ||
217 | |||
218 | input.count = 4; | ||
219 | input.pointer = params; | ||
220 | params[0].type = ACPI_TYPE_BUFFER; | ||
221 | params[0].buffer.length = sizeof(device_label_dsm_uuid); | ||
222 | params[0].buffer.pointer = (char *)device_label_dsm_uuid; | ||
223 | params[1].type = ACPI_TYPE_INTEGER; | ||
224 | params[1].integer.value = 0x02; | ||
225 | params[2].type = ACPI_TYPE_INTEGER; | ||
226 | params[2].integer.value = func; | ||
227 | params[3].type = ACPI_TYPE_PACKAGE; | ||
228 | params[3].package.count = 0; | ||
229 | params[3].package.elements = NULL; | ||
230 | |||
231 | err = acpi_evaluate_object(handle, "_DSM", &input, output); | ||
232 | if (err) | ||
233 | return -1; | ||
234 | |||
235 | obj = (union acpi_object *)output->pointer; | ||
236 | |||
237 | switch (obj->type) { | ||
238 | case ACPI_TYPE_PACKAGE: | ||
239 | if (obj->package.count != 2) | ||
240 | break; | ||
241 | len = obj->package.elements[0].integer.value; | ||
242 | if (buf) { | ||
243 | if (attribute == ACPI_ATTR_INDEX_SHOW) | ||
244 | scnprintf(buf, PAGE_SIZE, "%llu\n", | ||
245 | obj->package.elements[0].integer.value); | ||
246 | else if (attribute == ACPI_ATTR_LABEL_SHOW) | ||
247 | dsm_label_utf16s_to_utf8s(obj, buf); | ||
248 | kfree(output->pointer); | ||
249 | return strlen(buf); | ||
250 | } | ||
251 | kfree(output->pointer); | ||
252 | return len; | ||
253 | break; | ||
254 | default: | ||
255 | kfree(output->pointer); | ||
256 | } | ||
257 | return -1; | ||
258 | } | ||
259 | |||
260 | static bool | ||
261 | device_has_dsm(struct device *dev) | ||
262 | { | ||
263 | acpi_handle handle; | ||
264 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
265 | |||
266 | handle = DEVICE_ACPI_HANDLE(dev); | ||
267 | |||
268 | if (!handle) | ||
269 | return FALSE; | ||
270 | |||
271 | if (dsm_get_label(handle, DEVICE_LABEL_DSM, &output, NULL, | ||
272 | ACPI_ATTR_NONE) > 0) | ||
273 | return TRUE; | ||
274 | |||
275 | return FALSE; | ||
276 | } | ||
277 | |||
278 | static mode_t | ||
279 | acpi_index_string_exist(struct kobject *kobj, struct attribute *attr, int n) | ||
280 | { | ||
281 | struct device *dev; | ||
282 | |||
283 | dev = container_of(kobj, struct device, kobj); | ||
284 | |||
285 | if (device_has_dsm(dev)) | ||
286 | return S_IRUGO; | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static ssize_t | ||
292 | acpilabel_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
293 | { | ||
294 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
295 | acpi_handle handle; | ||
296 | int length; | ||
297 | |||
298 | handle = DEVICE_ACPI_HANDLE(dev); | ||
299 | |||
300 | if (!handle) | ||
301 | return -1; | ||
302 | |||
303 | length = dsm_get_label(handle, DEVICE_LABEL_DSM, | ||
304 | &output, buf, ACPI_ATTR_LABEL_SHOW); | ||
305 | |||
306 | if (length < 1) | ||
307 | return -1; | ||
308 | |||
309 | return length; | ||
310 | } | ||
311 | |||
312 | static ssize_t | ||
313 | acpiindex_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
314 | { | ||
315 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
316 | acpi_handle handle; | ||
317 | int length; | ||
318 | |||
319 | handle = DEVICE_ACPI_HANDLE(dev); | ||
320 | |||
321 | if (!handle) | ||
322 | return -1; | ||
323 | |||
324 | length = dsm_get_label(handle, DEVICE_LABEL_DSM, | ||
325 | &output, buf, ACPI_ATTR_INDEX_SHOW); | ||
326 | |||
327 | if (length < 0) | ||
328 | return -1; | ||
329 | |||
330 | return length; | ||
331 | |||
332 | } | ||
333 | |||
334 | static struct device_attribute acpi_attr_label = { | ||
335 | .attr = {.name = "label", .mode = 0444}, | ||
336 | .show = acpilabel_show, | ||
337 | }; | ||
338 | |||
339 | static struct device_attribute acpi_attr_index = { | ||
340 | .attr = {.name = "acpi_index", .mode = 0444}, | ||
341 | .show = acpiindex_show, | ||
342 | }; | ||
343 | |||
344 | static struct attribute *acpi_attributes[] = { | ||
345 | &acpi_attr_label.attr, | ||
346 | &acpi_attr_index.attr, | ||
347 | NULL, | ||
348 | }; | ||
349 | |||
350 | static struct attribute_group acpi_attr_group = { | ||
351 | .attrs = acpi_attributes, | ||
352 | .is_visible = acpi_index_string_exist, | ||
353 | }; | ||
354 | |||
355 | static int | ||
356 | pci_create_acpi_index_label_files(struct pci_dev *pdev) | ||
357 | { | ||
358 | return sysfs_create_group(&pdev->dev.kobj, &acpi_attr_group); | ||
359 | } | ||
360 | |||
361 | static int | ||
362 | pci_remove_acpi_index_label_files(struct pci_dev *pdev) | ||
363 | { | ||
364 | sysfs_remove_group(&pdev->dev.kobj, &acpi_attr_group); | ||
365 | return 0; | ||
366 | } | ||
367 | #endif | ||
368 | |||
134 | void pci_create_firmware_label_files(struct pci_dev *pdev) | 369 | void pci_create_firmware_label_files(struct pci_dev *pdev) |
135 | { | 370 | { |
136 | if (!pci_create_smbiosname_file(pdev)) | 371 | if (device_has_dsm(&pdev->dev)) |
137 | ; | 372 | pci_create_acpi_index_label_files(pdev); |
373 | else | ||
374 | pci_create_smbiosname_file(pdev); | ||
138 | } | 375 | } |
139 | 376 | ||
140 | void pci_remove_firmware_label_files(struct pci_dev *pdev) | 377 | void pci_remove_firmware_label_files(struct pci_dev *pdev) |
141 | { | 378 | { |
142 | pci_remove_smbiosname_file(pdev); | 379 | if (device_has_dsm(&pdev->dev)) |
380 | pci_remove_acpi_index_label_files(pdev); | ||
381 | else | ||
382 | pci_remove_smbiosname_file(pdev); | ||
143 | } | 383 | } |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index ea25e5bfcf23..c85438a367d5 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -1088,7 +1088,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev) | |||
1088 | attr->write = write_vpd_attr; | 1088 | attr->write = write_vpd_attr; |
1089 | retval = sysfs_create_bin_file(&dev->dev.kobj, attr); | 1089 | retval = sysfs_create_bin_file(&dev->dev.kobj, attr); |
1090 | if (retval) { | 1090 | if (retval) { |
1091 | kfree(dev->vpd->attr); | 1091 | kfree(attr); |
1092 | return retval; | 1092 | return retval; |
1093 | } | 1093 | } |
1094 | dev->vpd->attr = attr; | 1094 | dev->vpd->attr = attr; |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index f69d6e0fda75..a6ec200fe5ee 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -11,7 +11,7 @@ | |||
11 | extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env); | 11 | extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env); |
12 | extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); | 12 | extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); |
13 | extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); | 13 | extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); |
14 | #ifndef CONFIG_DMI | 14 | #if !defined(CONFIG_DMI) && !defined(CONFIG_ACPI) |
15 | static inline void pci_create_firmware_label_files(struct pci_dev *pdev) | 15 | static inline void pci_create_firmware_label_files(struct pci_dev *pdev) |
16 | { return; } | 16 | { return; } |
17 | static inline void pci_remove_firmware_label_files(struct pci_dev *pdev) | 17 | static inline void pci_remove_firmware_label_files(struct pci_dev *pdev) |
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index b3cf6223f63a..f62079ff06dd 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c | |||
@@ -27,6 +27,10 @@ | |||
27 | #include <linux/stddef.h> | 27 | #include <linux/stddef.h> |
28 | #include "aerdrv.h" | 28 | #include "aerdrv.h" |
29 | 29 | ||
30 | /* Override the existing corrected and uncorrected error masks */ | ||
31 | static int aer_mask_override; | ||
32 | module_param(aer_mask_override, bool, 0); | ||
33 | |||
30 | struct aer_error_inj { | 34 | struct aer_error_inj { |
31 | u8 bus; | 35 | u8 bus; |
32 | u8 dev; | 36 | u8 dev; |
@@ -322,7 +326,7 @@ static int aer_inject(struct aer_error_inj *einj) | |||
322 | unsigned long flags; | 326 | unsigned long flags; |
323 | unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn); | 327 | unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn); |
324 | int pos_cap_err, rp_pos_cap_err; | 328 | int pos_cap_err, rp_pos_cap_err; |
325 | u32 sever, cor_mask, uncor_mask; | 329 | u32 sever, cor_mask, uncor_mask, cor_mask_orig, uncor_mask_orig; |
326 | int ret = 0; | 330 | int ret = 0; |
327 | 331 | ||
328 | dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn); | 332 | dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn); |
@@ -361,6 +365,18 @@ static int aer_inject(struct aer_error_inj *einj) | |||
361 | goto out_put; | 365 | goto out_put; |
362 | } | 366 | } |
363 | 367 | ||
368 | if (aer_mask_override) { | ||
369 | cor_mask_orig = cor_mask; | ||
370 | cor_mask &= !(einj->cor_status); | ||
371 | pci_write_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK, | ||
372 | cor_mask); | ||
373 | |||
374 | uncor_mask_orig = uncor_mask; | ||
375 | uncor_mask &= !(einj->uncor_status); | ||
376 | pci_write_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK, | ||
377 | uncor_mask); | ||
378 | } | ||
379 | |||
364 | spin_lock_irqsave(&inject_lock, flags); | 380 | spin_lock_irqsave(&inject_lock, flags); |
365 | 381 | ||
366 | err = __find_aer_error_by_dev(dev); | 382 | err = __find_aer_error_by_dev(dev); |
@@ -378,14 +394,16 @@ static int aer_inject(struct aer_error_inj *einj) | |||
378 | err->header_log2 = einj->header_log2; | 394 | err->header_log2 = einj->header_log2; |
379 | err->header_log3 = einj->header_log3; | 395 | err->header_log3 = einj->header_log3; |
380 | 396 | ||
381 | if (einj->cor_status && !(einj->cor_status & ~cor_mask)) { | 397 | if (!aer_mask_override && einj->cor_status && |
398 | !(einj->cor_status & ~cor_mask)) { | ||
382 | ret = -EINVAL; | 399 | ret = -EINVAL; |
383 | printk(KERN_WARNING "The correctable error(s) is masked " | 400 | printk(KERN_WARNING "The correctable error(s) is masked " |
384 | "by device\n"); | 401 | "by device\n"); |
385 | spin_unlock_irqrestore(&inject_lock, flags); | 402 | spin_unlock_irqrestore(&inject_lock, flags); |
386 | goto out_put; | 403 | goto out_put; |
387 | } | 404 | } |
388 | if (einj->uncor_status && !(einj->uncor_status & ~uncor_mask)) { | 405 | if (!aer_mask_override && einj->uncor_status && |
406 | !(einj->uncor_status & ~uncor_mask)) { | ||
389 | ret = -EINVAL; | 407 | ret = -EINVAL; |
390 | printk(KERN_WARNING "The uncorrectable error(s) is masked " | 408 | printk(KERN_WARNING "The uncorrectable error(s) is masked " |
391 | "by device\n"); | 409 | "by device\n"); |
@@ -425,6 +443,13 @@ static int aer_inject(struct aer_error_inj *einj) | |||
425 | } | 443 | } |
426 | spin_unlock_irqrestore(&inject_lock, flags); | 444 | spin_unlock_irqrestore(&inject_lock, flags); |
427 | 445 | ||
446 | if (aer_mask_override) { | ||
447 | pci_write_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK, | ||
448 | cor_mask_orig); | ||
449 | pci_write_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK, | ||
450 | uncor_mask_orig); | ||
451 | } | ||
452 | |||
428 | ret = pci_bus_set_aer_ops(dev->bus); | 453 | ret = pci_bus_set_aer_ops(dev->bus); |
429 | if (ret) | 454 | if (ret) |
430 | goto out_put; | 455 | goto out_put; |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index c84900da3c59..44cbbbaa499d 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -764,6 +764,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, | |||
764 | if (pci_find_bus(pci_domain_nr(bus), max+1)) | 764 | if (pci_find_bus(pci_domain_nr(bus), max+1)) |
765 | goto out; | 765 | goto out; |
766 | child = pci_add_new_bus(bus, dev, ++max); | 766 | child = pci_add_new_bus(bus, dev, ++max); |
767 | if (!child) | ||
768 | goto out; | ||
767 | buses = (buses & 0xff000000) | 769 | buses = (buses & 0xff000000) |
768 | | ((unsigned int)(child->primary) << 0) | 770 | | ((unsigned int)(child->primary) << 0) |
769 | | ((unsigned int)(child->secondary) << 8) | 771 | | ((unsigned int)(child->secondary) << 8) |
@@ -777,7 +779,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, | |||
777 | buses &= ~0xff000000; | 779 | buses &= ~0xff000000; |
778 | buses |= CARDBUS_LATENCY_TIMER << 24; | 780 | buses |= CARDBUS_LATENCY_TIMER << 24; |
779 | } | 781 | } |
780 | 782 | ||
781 | /* | 783 | /* |
782 | * We need to blast all three values with a single write. | 784 | * We need to blast all three values with a single write. |
783 | */ | 785 | */ |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 53a786fd0d40..bd80f6378463 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -533,6 +533,17 @@ static void __devinit quirk_piix4_acpi(struct pci_dev *dev) | |||
533 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi); | 533 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi); |
534 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, quirk_piix4_acpi); | 534 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, quirk_piix4_acpi); |
535 | 535 | ||
536 | #define ICH_PMBASE 0x40 | ||
537 | #define ICH_ACPI_CNTL 0x44 | ||
538 | #define ICH4_ACPI_EN 0x10 | ||
539 | #define ICH6_ACPI_EN 0x80 | ||
540 | #define ICH4_GPIOBASE 0x58 | ||
541 | #define ICH4_GPIO_CNTL 0x5c | ||
542 | #define ICH4_GPIO_EN 0x10 | ||
543 | #define ICH6_GPIOBASE 0x48 | ||
544 | #define ICH6_GPIO_CNTL 0x4c | ||
545 | #define ICH6_GPIO_EN 0x10 | ||
546 | |||
536 | /* | 547 | /* |
537 | * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at | 548 | * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at |
538 | * 0x40 (128 bytes of ACPI, GPIO & TCO registers) | 549 | * 0x40 (128 bytes of ACPI, GPIO & TCO registers) |
@@ -541,12 +552,33 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, qui | |||
541 | static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev) | 552 | static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev) |
542 | { | 553 | { |
543 | u32 region; | 554 | u32 region; |
555 | u8 enable; | ||
544 | 556 | ||
545 | pci_read_config_dword(dev, 0x40, ®ion); | 557 | /* |
546 | quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH4 ACPI/GPIO/TCO"); | 558 | * The check for PCIBIOS_MIN_IO is to ensure we won't create a conflict |
559 | * with low legacy (and fixed) ports. We don't know the decoding | ||
560 | * priority and can't tell whether the legacy device or the one created | ||
561 | * here is really at that address. This happens on boards with broken | ||
562 | * BIOSes. | ||
563 | */ | ||
564 | |||
565 | pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); | ||
566 | if (enable & ICH4_ACPI_EN) { | ||
567 | pci_read_config_dword(dev, ICH_PMBASE, ®ion); | ||
568 | region &= PCI_BASE_ADDRESS_IO_MASK; | ||
569 | if (region >= PCIBIOS_MIN_IO) | ||
570 | quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, | ||
571 | "ICH4 ACPI/GPIO/TCO"); | ||
572 | } | ||
547 | 573 | ||
548 | pci_read_config_dword(dev, 0x58, ®ion); | 574 | pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable); |
549 | quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO"); | 575 | if (enable & ICH4_GPIO_EN) { |
576 | pci_read_config_dword(dev, ICH4_GPIOBASE, ®ion); | ||
577 | region &= PCI_BASE_ADDRESS_IO_MASK; | ||
578 | if (region >= PCIBIOS_MIN_IO) | ||
579 | quirk_io_region(dev, region, 64, | ||
580 | PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO"); | ||
581 | } | ||
550 | } | 582 | } |
551 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi); | 583 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi); |
552 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi); | 584 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi); |
@@ -562,12 +594,25 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, qui | |||
562 | static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev) | 594 | static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev) |
563 | { | 595 | { |
564 | u32 region; | 596 | u32 region; |
597 | u8 enable; | ||
565 | 598 | ||
566 | pci_read_config_dword(dev, 0x40, ®ion); | 599 | pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); |
567 | quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO"); | 600 | if (enable & ICH6_ACPI_EN) { |
601 | pci_read_config_dword(dev, ICH_PMBASE, ®ion); | ||
602 | region &= PCI_BASE_ADDRESS_IO_MASK; | ||
603 | if (region >= PCIBIOS_MIN_IO) | ||
604 | quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, | ||
605 | "ICH6 ACPI/GPIO/TCO"); | ||
606 | } | ||
568 | 607 | ||
569 | pci_read_config_dword(dev, 0x48, ®ion); | 608 | pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable); |
570 | quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO"); | 609 | if (enable & ICH4_GPIO_EN) { |
610 | pci_read_config_dword(dev, ICH6_GPIOBASE, ®ion); | ||
611 | region &= PCI_BASE_ADDRESS_IO_MASK; | ||
612 | if (region >= PCIBIOS_MIN_IO) | ||
613 | quirk_io_region(dev, region, 64, | ||
614 | PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO"); | ||
615 | } | ||
571 | } | 616 | } |
572 | 617 | ||
573 | static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize) | 618 | static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize) |
@@ -2618,58 +2663,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375, | |||
2618 | 2663 | ||
2619 | #endif /* CONFIG_PCI_MSI */ | 2664 | #endif /* CONFIG_PCI_MSI */ |
2620 | 2665 | ||
2621 | #ifdef CONFIG_PCI_IOV | ||
2622 | |||
2623 | /* | ||
2624 | * For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the | ||
2625 | * SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the | ||
2626 | * old Flash Memory Space. | ||
2627 | */ | ||
2628 | static void __devinit quirk_i82576_sriov(struct pci_dev *dev) | ||
2629 | { | ||
2630 | int pos, flags; | ||
2631 | u32 bar, start, size; | ||
2632 | |||
2633 | if (PAGE_SIZE > 0x10000) | ||
2634 | return; | ||
2635 | |||
2636 | flags = pci_resource_flags(dev, 0); | ||
2637 | if ((flags & PCI_BASE_ADDRESS_SPACE) != | ||
2638 | PCI_BASE_ADDRESS_SPACE_MEMORY || | ||
2639 | (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != | ||
2640 | PCI_BASE_ADDRESS_MEM_TYPE_32) | ||
2641 | return; | ||
2642 | |||
2643 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); | ||
2644 | if (!pos) | ||
2645 | return; | ||
2646 | |||
2647 | pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar); | ||
2648 | if (bar & PCI_BASE_ADDRESS_MEM_MASK) | ||
2649 | return; | ||
2650 | |||
2651 | start = pci_resource_start(dev, 1); | ||
2652 | size = pci_resource_len(dev, 1); | ||
2653 | if (!start || size != 0x400000 || start & (size - 1)) | ||
2654 | return; | ||
2655 | |||
2656 | pci_resource_flags(dev, 1) = 0; | ||
2657 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0); | ||
2658 | pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start); | ||
2659 | pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2); | ||
2660 | |||
2661 | dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n"); | ||
2662 | } | ||
2663 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov); | ||
2664 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov); | ||
2665 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov); | ||
2666 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov); | ||
2667 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov); | ||
2668 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov); | ||
2669 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov); | ||
2670 | |||
2671 | #endif /* CONFIG_PCI_IOV */ | ||
2672 | |||
2673 | /* Allow manual resource allocation for PCI hotplug bridges | 2666 | /* Allow manual resource allocation for PCI hotplug bridges |
2674 | * via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For | 2667 | * via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For |
2675 | * some PCI-PCI hotplug bridges, like PLX 6254 (former HINT HB6), | 2668 | * some PCI-PCI hotplug bridges, like PLX 6254 (former HINT HB6), |
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 66cb8f4cc5f4..89d0a6a88df7 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -33,11 +33,32 @@ struct resource_list_x { | |||
33 | struct pci_dev *dev; | 33 | struct pci_dev *dev; |
34 | resource_size_t start; | 34 | resource_size_t start; |
35 | resource_size_t end; | 35 | resource_size_t end; |
36 | resource_size_t add_size; | ||
36 | unsigned long flags; | 37 | unsigned long flags; |
37 | }; | 38 | }; |
38 | 39 | ||
39 | static void add_to_failed_list(struct resource_list_x *head, | 40 | #define free_list(type, head) do { \ |
40 | struct pci_dev *dev, struct resource *res) | 41 | struct type *list, *tmp; \ |
42 | for (list = (head)->next; list;) { \ | ||
43 | tmp = list; \ | ||
44 | list = list->next; \ | ||
45 | kfree(tmp); \ | ||
46 | } \ | ||
47 | (head)->next = NULL; \ | ||
48 | } while (0) | ||
49 | |||
50 | /** | ||
51 | * add_to_list() - add a new resource tracker to the list | ||
52 | * @head: Head of the list | ||
53 | * @dev: device corresponding to which the resource | ||
54 | * belongs | ||
55 | * @res: The resource to be tracked | ||
56 | * @add_size: additional size to be optionally added | ||
57 | * to the resource | ||
58 | */ | ||
59 | static void add_to_list(struct resource_list_x *head, | ||
60 | struct pci_dev *dev, struct resource *res, | ||
61 | resource_size_t add_size) | ||
41 | { | 62 | { |
42 | struct resource_list_x *list = head; | 63 | struct resource_list_x *list = head; |
43 | struct resource_list_x *ln = list->next; | 64 | struct resource_list_x *ln = list->next; |
@@ -45,7 +66,7 @@ static void add_to_failed_list(struct resource_list_x *head, | |||
45 | 66 | ||
46 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | 67 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); |
47 | if (!tmp) { | 68 | if (!tmp) { |
48 | pr_warning("add_to_failed_list: kmalloc() failed!\n"); | 69 | pr_warning("add_to_list: kmalloc() failed!\n"); |
49 | return; | 70 | return; |
50 | } | 71 | } |
51 | 72 | ||
@@ -55,20 +76,14 @@ static void add_to_failed_list(struct resource_list_x *head, | |||
55 | tmp->start = res->start; | 76 | tmp->start = res->start; |
56 | tmp->end = res->end; | 77 | tmp->end = res->end; |
57 | tmp->flags = res->flags; | 78 | tmp->flags = res->flags; |
79 | tmp->add_size = add_size; | ||
58 | list->next = tmp; | 80 | list->next = tmp; |
59 | } | 81 | } |
60 | 82 | ||
61 | static void free_failed_list(struct resource_list_x *head) | 83 | static void add_to_failed_list(struct resource_list_x *head, |
84 | struct pci_dev *dev, struct resource *res) | ||
62 | { | 85 | { |
63 | struct resource_list_x *list, *tmp; | 86 | add_to_list(head, dev, res, 0); |
64 | |||
65 | for (list = head->next; list;) { | ||
66 | tmp = list; | ||
67 | list = list->next; | ||
68 | kfree(tmp); | ||
69 | } | ||
70 | |||
71 | head->next = NULL; | ||
72 | } | 87 | } |
73 | 88 | ||
74 | static void __dev_sort_resources(struct pci_dev *dev, | 89 | static void __dev_sort_resources(struct pci_dev *dev, |
@@ -91,18 +106,88 @@ static void __dev_sort_resources(struct pci_dev *dev, | |||
91 | pdev_sort_resources(dev, head); | 106 | pdev_sort_resources(dev, head); |
92 | } | 107 | } |
93 | 108 | ||
94 | static void __assign_resources_sorted(struct resource_list *head, | 109 | static inline void reset_resource(struct resource *res) |
95 | struct resource_list_x *fail_head) | 110 | { |
111 | res->start = 0; | ||
112 | res->end = 0; | ||
113 | res->flags = 0; | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * adjust_resources_sorted() - satisfy any additional resource requests | ||
118 | * | ||
119 | * @add_head : head of the list tracking requests requiring additional | ||
120 | * resources | ||
121 | * @head : head of the list tracking requests with allocated | ||
122 | * resources | ||
123 | * | ||
124 | * Walk through each element of the add_head and try to procure | ||
125 | * additional resources for the element, provided the element | ||
126 | * is in the head list. | ||
127 | */ | ||
128 | static void adjust_resources_sorted(struct resource_list_x *add_head, | ||
129 | struct resource_list *head) | ||
96 | { | 130 | { |
97 | struct resource *res; | 131 | struct resource *res; |
98 | struct resource_list *list, *tmp; | 132 | struct resource_list_x *list, *tmp, *prev; |
133 | struct resource_list *hlist; | ||
134 | resource_size_t add_size; | ||
99 | int idx; | 135 | int idx; |
100 | 136 | ||
101 | for (list = head->next; list;) { | 137 | prev = add_head; |
138 | for (list = add_head->next; list;) { | ||
102 | res = list->res; | 139 | res = list->res; |
140 | /* skip resource that has been reset */ | ||
141 | if (!res->flags) | ||
142 | goto out; | ||
143 | |||
144 | /* skip this resource if not found in head list */ | ||
145 | for (hlist = head->next; hlist && hlist->res != res; | ||
146 | hlist = hlist->next); | ||
147 | if (!hlist) { /* just skip */ | ||
148 | prev = list; | ||
149 | list = list->next; | ||
150 | continue; | ||
151 | } | ||
152 | |||
103 | idx = res - &list->dev->resource[0]; | 153 | idx = res - &list->dev->resource[0]; |
154 | add_size=list->add_size; | ||
155 | if (!resource_size(res) && add_size) { | ||
156 | res->end = res->start + add_size - 1; | ||
157 | if(pci_assign_resource(list->dev, idx)) | ||
158 | reset_resource(res); | ||
159 | } else if (add_size) { | ||
160 | adjust_resource(res, res->start, | ||
161 | resource_size(res) + add_size); | ||
162 | } | ||
163 | out: | ||
164 | tmp = list; | ||
165 | prev->next = list = list->next; | ||
166 | kfree(tmp); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * assign_requested_resources_sorted() - satisfy resource requests | ||
172 | * | ||
173 | * @head : head of the list tracking requests for resources | ||
174 | * @failed_list : head of the list tracking requests that could | ||
175 | * not be allocated | ||
176 | * | ||
177 | * Satisfy resource requests of each element in the list. Add | ||
178 | * requests that could not satisfied to the failed_list. | ||
179 | */ | ||
180 | static void assign_requested_resources_sorted(struct resource_list *head, | ||
181 | struct resource_list_x *fail_head) | ||
182 | { | ||
183 | struct resource *res; | ||
184 | struct resource_list *list; | ||
185 | int idx; | ||
104 | 186 | ||
105 | if (pci_assign_resource(list->dev, idx)) { | 187 | for (list = head->next; list; list = list->next) { |
188 | res = list->res; | ||
189 | idx = res - &list->dev->resource[0]; | ||
190 | if (resource_size(res) && pci_assign_resource(list->dev, idx)) { | ||
106 | if (fail_head && !pci_is_root_bus(list->dev->bus)) { | 191 | if (fail_head && !pci_is_root_bus(list->dev->bus)) { |
107 | /* | 192 | /* |
108 | * if the failed res is for ROM BAR, and it will | 193 | * if the failed res is for ROM BAR, and it will |
@@ -112,16 +197,25 @@ static void __assign_resources_sorted(struct resource_list *head, | |||
112 | (!(res->flags & IORESOURCE_ROM_ENABLE)))) | 197 | (!(res->flags & IORESOURCE_ROM_ENABLE)))) |
113 | add_to_failed_list(fail_head, list->dev, res); | 198 | add_to_failed_list(fail_head, list->dev, res); |
114 | } | 199 | } |
115 | res->start = 0; | 200 | reset_resource(res); |
116 | res->end = 0; | ||
117 | res->flags = 0; | ||
118 | } | 201 | } |
119 | tmp = list; | ||
120 | list = list->next; | ||
121 | kfree(tmp); | ||
122 | } | 202 | } |
123 | } | 203 | } |
124 | 204 | ||
205 | static void __assign_resources_sorted(struct resource_list *head, | ||
206 | struct resource_list_x *add_head, | ||
207 | struct resource_list_x *fail_head) | ||
208 | { | ||
209 | /* Satisfy the must-have resource requests */ | ||
210 | assign_requested_resources_sorted(head, fail_head); | ||
211 | |||
212 | /* Try to satisfy any additional nice-to-have resource | ||
213 | requests */ | ||
214 | if (add_head) | ||
215 | adjust_resources_sorted(add_head, head); | ||
216 | free_list(resource_list, head); | ||
217 | } | ||
218 | |||
125 | static void pdev_assign_resources_sorted(struct pci_dev *dev, | 219 | static void pdev_assign_resources_sorted(struct pci_dev *dev, |
126 | struct resource_list_x *fail_head) | 220 | struct resource_list_x *fail_head) |
127 | { | 221 | { |
@@ -129,11 +223,12 @@ static void pdev_assign_resources_sorted(struct pci_dev *dev, | |||
129 | 223 | ||
130 | head.next = NULL; | 224 | head.next = NULL; |
131 | __dev_sort_resources(dev, &head); | 225 | __dev_sort_resources(dev, &head); |
132 | __assign_resources_sorted(&head, fail_head); | 226 | __assign_resources_sorted(&head, NULL, fail_head); |
133 | 227 | ||
134 | } | 228 | } |
135 | 229 | ||
136 | static void pbus_assign_resources_sorted(const struct pci_bus *bus, | 230 | static void pbus_assign_resources_sorted(const struct pci_bus *bus, |
231 | struct resource_list_x *add_head, | ||
137 | struct resource_list_x *fail_head) | 232 | struct resource_list_x *fail_head) |
138 | { | 233 | { |
139 | struct pci_dev *dev; | 234 | struct pci_dev *dev; |
@@ -143,7 +238,7 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus, | |||
143 | list_for_each_entry(dev, &bus->devices, bus_list) | 238 | list_for_each_entry(dev, &bus->devices, bus_list) |
144 | __dev_sort_resources(dev, &head); | 239 | __dev_sort_resources(dev, &head); |
145 | 240 | ||
146 | __assign_resources_sorted(&head, fail_head); | 241 | __assign_resources_sorted(&head, add_head, fail_head); |
147 | } | 242 | } |
148 | 243 | ||
149 | void pci_setup_cardbus(struct pci_bus *bus) | 244 | void pci_setup_cardbus(struct pci_bus *bus) |
@@ -404,15 +499,62 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon | |||
404 | return NULL; | 499 | return NULL; |
405 | } | 500 | } |
406 | 501 | ||
407 | /* Sizing the IO windows of the PCI-PCI bridge is trivial, | 502 | static resource_size_t calculate_iosize(resource_size_t size, |
408 | since these windows have 4K granularity and the IO ranges | 503 | resource_size_t min_size, |
409 | of non-bridge PCI devices are limited to 256 bytes. | 504 | resource_size_t size1, |
410 | We must be careful with the ISA aliasing though. */ | 505 | resource_size_t old_size, |
411 | static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | 506 | resource_size_t align) |
507 | { | ||
508 | if (size < min_size) | ||
509 | size = min_size; | ||
510 | if (old_size == 1 ) | ||
511 | old_size = 0; | ||
512 | /* To be fixed in 2.5: we should have sort of HAVE_ISA | ||
513 | flag in the struct pci_bus. */ | ||
514 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) | ||
515 | size = (size & 0xff) + ((size & ~0xffUL) << 2); | ||
516 | #endif | ||
517 | size = ALIGN(size + size1, align); | ||
518 | if (size < old_size) | ||
519 | size = old_size; | ||
520 | return size; | ||
521 | } | ||
522 | |||
523 | static resource_size_t calculate_memsize(resource_size_t size, | ||
524 | resource_size_t min_size, | ||
525 | resource_size_t size1, | ||
526 | resource_size_t old_size, | ||
527 | resource_size_t align) | ||
528 | { | ||
529 | if (size < min_size) | ||
530 | size = min_size; | ||
531 | if (old_size == 1 ) | ||
532 | old_size = 0; | ||
533 | if (size < old_size) | ||
534 | size = old_size; | ||
535 | size = ALIGN(size + size1, align); | ||
536 | return size; | ||
537 | } | ||
538 | |||
539 | /** | ||
540 | * pbus_size_io() - size the io window of a given bus | ||
541 | * | ||
542 | * @bus : the bus | ||
543 | * @min_size : the minimum io window that must to be allocated | ||
544 | * @add_size : additional optional io window | ||
545 | * @add_head : track the additional io window on this list | ||
546 | * | ||
547 | * Sizing the IO windows of the PCI-PCI bridge is trivial, | ||
548 | * since these windows have 4K granularity and the IO ranges | ||
549 | * of non-bridge PCI devices are limited to 256 bytes. | ||
550 | * We must be careful with the ISA aliasing though. | ||
551 | */ | ||
552 | static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, | ||
553 | resource_size_t add_size, struct resource_list_x *add_head) | ||
412 | { | 554 | { |
413 | struct pci_dev *dev; | 555 | struct pci_dev *dev; |
414 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); | 556 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); |
415 | unsigned long size = 0, size1 = 0, old_size; | 557 | unsigned long size = 0, size0 = 0, size1 = 0; |
416 | 558 | ||
417 | if (!b_res) | 559 | if (!b_res) |
418 | return; | 560 | return; |
@@ -435,20 +577,12 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | |||
435 | size1 += r_size; | 577 | size1 += r_size; |
436 | } | 578 | } |
437 | } | 579 | } |
438 | if (size < min_size) | 580 | size0 = calculate_iosize(size, min_size, size1, |
439 | size = min_size; | 581 | resource_size(b_res), 4096); |
440 | old_size = resource_size(b_res); | 582 | size1 = !add_size? size0: |
441 | if (old_size == 1) | 583 | calculate_iosize(size, min_size+add_size, size1, |
442 | old_size = 0; | 584 | resource_size(b_res), 4096); |
443 | /* To be fixed in 2.5: we should have sort of HAVE_ISA | 585 | if (!size0 && !size1) { |
444 | flag in the struct pci_bus. */ | ||
445 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) | ||
446 | size = (size & 0xff) + ((size & ~0xffUL) << 2); | ||
447 | #endif | ||
448 | size = ALIGN(size + size1, 4096); | ||
449 | if (size < old_size) | ||
450 | size = old_size; | ||
451 | if (!size) { | ||
452 | if (b_res->start || b_res->end) | 586 | if (b_res->start || b_res->end) |
453 | dev_info(&bus->self->dev, "disabling bridge window " | 587 | dev_info(&bus->self->dev, "disabling bridge window " |
454 | "%pR to [bus %02x-%02x] (unused)\n", b_res, | 588 | "%pR to [bus %02x-%02x] (unused)\n", b_res, |
@@ -458,17 +592,30 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size) | |||
458 | } | 592 | } |
459 | /* Alignment of the IO window is always 4K */ | 593 | /* Alignment of the IO window is always 4K */ |
460 | b_res->start = 4096; | 594 | b_res->start = 4096; |
461 | b_res->end = b_res->start + size - 1; | 595 | b_res->end = b_res->start + size0 - 1; |
462 | b_res->flags |= IORESOURCE_STARTALIGN; | 596 | b_res->flags |= IORESOURCE_STARTALIGN; |
597 | if (size1 > size0 && add_head) | ||
598 | add_to_list(add_head, bus->self, b_res, size1-size0); | ||
463 | } | 599 | } |
464 | 600 | ||
465 | /* Calculate the size of the bus and minimal alignment which | 601 | /** |
466 | guarantees that all child resources fit in this size. */ | 602 | * pbus_size_mem() - size the memory window of a given bus |
603 | * | ||
604 | * @bus : the bus | ||
605 | * @min_size : the minimum memory window that must to be allocated | ||
606 | * @add_size : additional optional memory window | ||
607 | * @add_head : track the additional memory window on this list | ||
608 | * | ||
609 | * Calculate the size of the bus and minimal alignment which | ||
610 | * guarantees that all child resources fit in this size. | ||
611 | */ | ||
467 | static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | 612 | static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, |
468 | unsigned long type, resource_size_t min_size) | 613 | unsigned long type, resource_size_t min_size, |
614 | resource_size_t add_size, | ||
615 | struct resource_list_x *add_head) | ||
469 | { | 616 | { |
470 | struct pci_dev *dev; | 617 | struct pci_dev *dev; |
471 | resource_size_t min_align, align, size, old_size; | 618 | resource_size_t min_align, align, size, size0, size1; |
472 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ | 619 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ |
473 | int order, max_order; | 620 | int order, max_order; |
474 | struct resource *b_res = find_free_bus_resource(bus, type); | 621 | struct resource *b_res = find_free_bus_resource(bus, type); |
@@ -516,14 +663,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
516 | mem64_mask &= r->flags & IORESOURCE_MEM_64; | 663 | mem64_mask &= r->flags & IORESOURCE_MEM_64; |
517 | } | 664 | } |
518 | } | 665 | } |
519 | if (size < min_size) | ||
520 | size = min_size; | ||
521 | old_size = resource_size(b_res); | ||
522 | if (old_size == 1) | ||
523 | old_size = 0; | ||
524 | if (size < old_size) | ||
525 | size = old_size; | ||
526 | |||
527 | align = 0; | 666 | align = 0; |
528 | min_align = 0; | 667 | min_align = 0; |
529 | for (order = 0; order <= max_order; order++) { | 668 | for (order = 0; order <= max_order; order++) { |
@@ -537,8 +676,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
537 | min_align = align1 >> 1; | 676 | min_align = align1 >> 1; |
538 | align += aligns[order]; | 677 | align += aligns[order]; |
539 | } | 678 | } |
540 | size = ALIGN(size, min_align); | 679 | size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), align); |
541 | if (!size) { | 680 | size1 = !add_size ? size : |
681 | calculate_memsize(size, min_size+add_size, 0, | ||
682 | resource_size(b_res), align); | ||
683 | if (!size0 && !size1) { | ||
542 | if (b_res->start || b_res->end) | 684 | if (b_res->start || b_res->end) |
543 | dev_info(&bus->self->dev, "disabling bridge window " | 685 | dev_info(&bus->self->dev, "disabling bridge window " |
544 | "%pR to [bus %02x-%02x] (unused)\n", b_res, | 686 | "%pR to [bus %02x-%02x] (unused)\n", b_res, |
@@ -547,9 +689,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
547 | return 1; | 689 | return 1; |
548 | } | 690 | } |
549 | b_res->start = min_align; | 691 | b_res->start = min_align; |
550 | b_res->end = size + min_align - 1; | 692 | b_res->end = size0 + min_align - 1; |
551 | b_res->flags |= IORESOURCE_STARTALIGN; | 693 | b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask; |
552 | b_res->flags |= mem64_mask; | 694 | if (size1 > size0 && add_head) |
695 | add_to_list(add_head, bus->self, b_res, size1-size0); | ||
553 | return 1; | 696 | return 1; |
554 | } | 697 | } |
555 | 698 | ||
@@ -602,11 +745,12 @@ static void pci_bus_size_cardbus(struct pci_bus *bus) | |||
602 | } | 745 | } |
603 | } | 746 | } |
604 | 747 | ||
605 | void __ref pci_bus_size_bridges(struct pci_bus *bus) | 748 | void __ref __pci_bus_size_bridges(struct pci_bus *bus, |
749 | struct resource_list_x *add_head) | ||
606 | { | 750 | { |
607 | struct pci_dev *dev; | 751 | struct pci_dev *dev; |
608 | unsigned long mask, prefmask; | 752 | unsigned long mask, prefmask; |
609 | resource_size_t min_mem_size = 0, min_io_size = 0; | 753 | resource_size_t additional_mem_size = 0, additional_io_size = 0; |
610 | 754 | ||
611 | list_for_each_entry(dev, &bus->devices, bus_list) { | 755 | list_for_each_entry(dev, &bus->devices, bus_list) { |
612 | struct pci_bus *b = dev->subordinate; | 756 | struct pci_bus *b = dev->subordinate; |
@@ -620,7 +764,7 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
620 | 764 | ||
621 | case PCI_CLASS_BRIDGE_PCI: | 765 | case PCI_CLASS_BRIDGE_PCI: |
622 | default: | 766 | default: |
623 | pci_bus_size_bridges(b); | 767 | __pci_bus_size_bridges(b, add_head); |
624 | break; | 768 | break; |
625 | } | 769 | } |
626 | } | 770 | } |
@@ -637,11 +781,14 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
637 | case PCI_CLASS_BRIDGE_PCI: | 781 | case PCI_CLASS_BRIDGE_PCI: |
638 | pci_bridge_check_ranges(bus); | 782 | pci_bridge_check_ranges(bus); |
639 | if (bus->self->is_hotplug_bridge) { | 783 | if (bus->self->is_hotplug_bridge) { |
640 | min_io_size = pci_hotplug_io_size; | 784 | additional_io_size = pci_hotplug_io_size; |
641 | min_mem_size = pci_hotplug_mem_size; | 785 | additional_mem_size = pci_hotplug_mem_size; |
642 | } | 786 | } |
787 | /* | ||
788 | * Follow thru | ||
789 | */ | ||
643 | default: | 790 | default: |
644 | pbus_size_io(bus, min_io_size); | 791 | pbus_size_io(bus, 0, additional_io_size, add_head); |
645 | /* If the bridge supports prefetchable range, size it | 792 | /* If the bridge supports prefetchable range, size it |
646 | separately. If it doesn't, or its prefetchable window | 793 | separately. If it doesn't, or its prefetchable window |
647 | has already been allocated by arch code, try | 794 | has already been allocated by arch code, try |
@@ -649,30 +796,36 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
649 | resources. */ | 796 | resources. */ |
650 | mask = IORESOURCE_MEM; | 797 | mask = IORESOURCE_MEM; |
651 | prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; | 798 | prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; |
652 | if (pbus_size_mem(bus, prefmask, prefmask, min_mem_size)) | 799 | if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, add_head)) |
653 | mask = prefmask; /* Success, size non-prefetch only. */ | 800 | mask = prefmask; /* Success, size non-prefetch only. */ |
654 | else | 801 | else |
655 | min_mem_size += min_mem_size; | 802 | additional_mem_size += additional_mem_size; |
656 | pbus_size_mem(bus, mask, IORESOURCE_MEM, min_mem_size); | 803 | pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, add_head); |
657 | break; | 804 | break; |
658 | } | 805 | } |
659 | } | 806 | } |
807 | |||
808 | void __ref pci_bus_size_bridges(struct pci_bus *bus) | ||
809 | { | ||
810 | __pci_bus_size_bridges(bus, NULL); | ||
811 | } | ||
660 | EXPORT_SYMBOL(pci_bus_size_bridges); | 812 | EXPORT_SYMBOL(pci_bus_size_bridges); |
661 | 813 | ||
662 | static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, | 814 | static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, |
815 | struct resource_list_x *add_head, | ||
663 | struct resource_list_x *fail_head) | 816 | struct resource_list_x *fail_head) |
664 | { | 817 | { |
665 | struct pci_bus *b; | 818 | struct pci_bus *b; |
666 | struct pci_dev *dev; | 819 | struct pci_dev *dev; |
667 | 820 | ||
668 | pbus_assign_resources_sorted(bus, fail_head); | 821 | pbus_assign_resources_sorted(bus, add_head, fail_head); |
669 | 822 | ||
670 | list_for_each_entry(dev, &bus->devices, bus_list) { | 823 | list_for_each_entry(dev, &bus->devices, bus_list) { |
671 | b = dev->subordinate; | 824 | b = dev->subordinate; |
672 | if (!b) | 825 | if (!b) |
673 | continue; | 826 | continue; |
674 | 827 | ||
675 | __pci_bus_assign_resources(b, fail_head); | 828 | __pci_bus_assign_resources(b, add_head, fail_head); |
676 | 829 | ||
677 | switch (dev->class >> 8) { | 830 | switch (dev->class >> 8) { |
678 | case PCI_CLASS_BRIDGE_PCI: | 831 | case PCI_CLASS_BRIDGE_PCI: |
@@ -694,7 +847,7 @@ static void __ref __pci_bus_assign_resources(const struct pci_bus *bus, | |||
694 | 847 | ||
695 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) | 848 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) |
696 | { | 849 | { |
697 | __pci_bus_assign_resources(bus, NULL); | 850 | __pci_bus_assign_resources(bus, NULL, NULL); |
698 | } | 851 | } |
699 | EXPORT_SYMBOL(pci_bus_assign_resources); | 852 | EXPORT_SYMBOL(pci_bus_assign_resources); |
700 | 853 | ||
@@ -709,7 +862,7 @@ static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge, | |||
709 | if (!b) | 862 | if (!b) |
710 | return; | 863 | return; |
711 | 864 | ||
712 | __pci_bus_assign_resources(b, fail_head); | 865 | __pci_bus_assign_resources(b, NULL, fail_head); |
713 | 866 | ||
714 | switch (bridge->class >> 8) { | 867 | switch (bridge->class >> 8) { |
715 | case PCI_CLASS_BRIDGE_PCI: | 868 | case PCI_CLASS_BRIDGE_PCI: |
@@ -842,17 +995,21 @@ void __init | |||
842 | pci_assign_unassigned_resources(void) | 995 | pci_assign_unassigned_resources(void) |
843 | { | 996 | { |
844 | struct pci_bus *bus; | 997 | struct pci_bus *bus; |
845 | 998 | struct resource_list_x add_list; /* list of resources that | |
999 | want additional resources */ | ||
1000 | add_list.next = NULL; | ||
846 | /* Depth first, calculate sizes and alignments of all | 1001 | /* Depth first, calculate sizes and alignments of all |
847 | subordinate buses. */ | 1002 | subordinate buses. */ |
848 | list_for_each_entry(bus, &pci_root_buses, node) { | 1003 | list_for_each_entry(bus, &pci_root_buses, node) { |
849 | pci_bus_size_bridges(bus); | 1004 | __pci_bus_size_bridges(bus, &add_list); |
850 | } | 1005 | } |
1006 | |||
851 | /* Depth last, allocate resources and update the hardware. */ | 1007 | /* Depth last, allocate resources and update the hardware. */ |
852 | list_for_each_entry(bus, &pci_root_buses, node) { | 1008 | list_for_each_entry(bus, &pci_root_buses, node) { |
853 | pci_bus_assign_resources(bus); | 1009 | __pci_bus_assign_resources(bus, &add_list, NULL); |
854 | pci_enable_bridges(bus); | 1010 | pci_enable_bridges(bus); |
855 | } | 1011 | } |
1012 | BUG_ON(add_list.next); | ||
856 | 1013 | ||
857 | /* dump the resource on buses */ | 1014 | /* dump the resource on buses */ |
858 | list_for_each_entry(bus, &pci_root_buses, node) { | 1015 | list_for_each_entry(bus, &pci_root_buses, node) { |
@@ -882,7 +1039,7 @@ again: | |||
882 | 1039 | ||
883 | if (tried_times >= 2) { | 1040 | if (tried_times >= 2) { |
884 | /* still fail, don't need to try more */ | 1041 | /* still fail, don't need to try more */ |
885 | free_failed_list(&head); | 1042 | free_list(resource_list_x, &head); |
886 | goto enable_all; | 1043 | goto enable_all; |
887 | } | 1044 | } |
888 | 1045 | ||
@@ -913,7 +1070,7 @@ again: | |||
913 | 1070 | ||
914 | list = list->next; | 1071 | list = list->next; |
915 | } | 1072 | } |
916 | free_failed_list(&head); | 1073 | free_list(resource_list_x, &head); |
917 | 1074 | ||
918 | goto again; | 1075 | goto again; |
919 | 1076 | ||