diff options
| -rw-r--r-- | Documentation/ABI/testing/sysfs-bus-pci | 31 | ||||
| -rw-r--r-- | arch/x86/pci/irq.c | 15 | ||||
| -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 | ||||
| -rw-r--r-- | include/linux/pci.h | 5 | ||||
| -rw-r--r-- | include/linux/pci_ids.h | 3 |
14 files changed, 614 insertions, 171 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci index f979d825d112..36bf454ba855 100644 --- a/Documentation/ABI/testing/sysfs-bus-pci +++ b/Documentation/ABI/testing/sysfs-bus-pci | |||
| @@ -145,9 +145,11 @@ Date: July 2010 | |||
| 145 | Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com | 145 | Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com |
| 146 | Description: | 146 | Description: |
| 147 | Reading this attribute will provide the firmware | 147 | Reading this attribute will provide the firmware |
| 148 | given name(SMBIOS type 41 string) of the PCI device. | 148 | given name (SMBIOS type 41 string or ACPI _DSM string) of |
| 149 | The attribute will be created only if the firmware | 149 | the PCI device. The attribute will be created only |
| 150 | has given a name to the PCI device. | 150 | if the firmware has given a name to the PCI device. |
| 151 | ACPI _DSM string name will be given priority if the | ||
| 152 | system firmware provides SMBIOS type 41 string also. | ||
| 151 | Users: | 153 | Users: |
| 152 | Userspace applications interested in knowing the | 154 | Userspace applications interested in knowing the |
| 153 | firmware assigned name of the PCI device. | 155 | firmware assigned name of the PCI device. |
| @@ -157,12 +159,27 @@ Date: July 2010 | |||
| 157 | Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com | 159 | Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com |
| 158 | Description: | 160 | Description: |
| 159 | Reading this attribute will provide the firmware | 161 | Reading this attribute will provide the firmware |
| 160 | given instance(SMBIOS type 41 device type instance) | 162 | given instance (SMBIOS type 41 device type instance) of the |
| 161 | of the PCI device. The attribute will be created | 163 | PCI device. The attribute will be created only if the firmware |
| 162 | only if the firmware has given a device type instance | 164 | has given an instance number to the PCI device. |
| 163 | to the PCI device. | ||
| 164 | Users: | 165 | Users: |
| 165 | Userspace applications interested in knowing the | 166 | Userspace applications interested in knowing the |
| 166 | firmware assigned device type instance of the PCI | 167 | firmware assigned device type instance of the PCI |
| 167 | device that can help in understanding the firmware | 168 | device that can help in understanding the firmware |
| 168 | intended order of the PCI device. | 169 | intended order of the PCI device. |
| 170 | |||
| 171 | What: /sys/bus/pci/devices/.../acpi_index | ||
| 172 | Date: July 2010 | ||
| 173 | Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com | ||
| 174 | Description: | ||
| 175 | Reading this attribute will provide the firmware | ||
| 176 | given instance (ACPI _DSM instance number) of the PCI device. | ||
| 177 | The attribute will be created only if the firmware has given | ||
| 178 | an instance number to the PCI device. ACPI _DSM instance number | ||
| 179 | will be given priority if the system firmware provides SMBIOS | ||
| 180 | type 41 device type instance also. | ||
| 181 | Users: | ||
| 182 | Userspace applications interested in knowing the | ||
| 183 | firmware assigned instance number of the PCI | ||
| 184 | device that can help in understanding the firmware | ||
| 185 | intended order of the PCI device. | ||
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 87e6c8323117..8201165bae28 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c | |||
| @@ -597,21 +597,18 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route | |||
| 597 | return 1; | 597 | return 1; |
| 598 | } | 598 | } |
| 599 | 599 | ||
| 600 | if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN) && | 600 | if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN && |
| 601 | (device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX)) { | 601 | device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX) |
| 602 | || (device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN && | ||
| 603 | device <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX) | ||
| 604 | || (device >= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN && | ||
| 605 | device <= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX)) { | ||
| 602 | r->name = "PIIX/ICH"; | 606 | r->name = "PIIX/ICH"; |
| 603 | r->get = pirq_piix_get; | 607 | r->get = pirq_piix_get; |
| 604 | r->set = pirq_piix_set; | 608 | r->set = pirq_piix_set; |
| 605 | return 1; | 609 | return 1; |
| 606 | } | 610 | } |
| 607 | 611 | ||
| 608 | if ((device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN) && | ||
| 609 | (device <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX)) { | ||
| 610 | r->name = "PIIX/ICH"; | ||
| 611 | r->get = pirq_piix_get; | ||
| 612 | r->set = pirq_piix_set; | ||
| 613 | return 1; | ||
| 614 | } | ||
| 615 | return 0; | 612 | return 0; |
| 616 | } | 613 | } |
| 617 | 614 | ||
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 | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index ff5bccb87136..16c9f2e61977 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
| @@ -1191,6 +1191,11 @@ static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
| 1191 | return 0; | 1191 | return 0; |
| 1192 | } | 1192 | } |
| 1193 | 1193 | ||
| 1194 | static inline int pci_wake_from_d3(struct pci_dev *dev, bool enable) | ||
| 1195 | { | ||
| 1196 | return 0; | ||
| 1197 | } | ||
| 1198 | |||
| 1194 | static inline pci_power_t pci_choose_state(struct pci_dev *dev, | 1199 | static inline pci_power_t pci_choose_state(struct pci_dev *dev, |
| 1195 | pm_message_t state) | 1200 | pm_message_t state) |
| 1196 | { | 1201 | { |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 511e5ee809ef..bda221dfaf0a 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
| @@ -2483,6 +2483,9 @@ | |||
| 2483 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 | 2483 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 |
| 2484 | #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0 0x1d40 | 2484 | #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0 0x1d40 |
| 2485 | #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1 0x1d41 | 2485 | #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1 0x1d41 |
| 2486 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN 0x2310 | ||
| 2487 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX 0x231f | ||
| 2488 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 | ||
| 2486 | #define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 | 2489 | #define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 |
| 2487 | #define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411 | 2490 | #define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411 |
| 2488 | #define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413 | 2491 | #define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413 |
