diff options
24 files changed, 281 insertions, 291 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index f084af0cb8e0..8dd7248508a9 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -1974,15 +1974,18 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 1974 | force Enable ASPM even on devices that claim not to support it. | 1974 | force Enable ASPM even on devices that claim not to support it. |
| 1975 | WARNING: Forcing ASPM on may cause system lockups. | 1975 | WARNING: Forcing ASPM on may cause system lockups. |
| 1976 | 1976 | ||
| 1977 | pcie_ports= [PCIE] PCIe ports handling: | ||
| 1978 | auto Ask the BIOS whether or not to use native PCIe services | ||
| 1979 | associated with PCIe ports (PME, hot-plug, AER). Use | ||
| 1980 | them only if that is allowed by the BIOS. | ||
| 1981 | native Use native PCIe services associated with PCIe ports | ||
| 1982 | unconditionally. | ||
| 1983 | compat Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe | ||
| 1984 | ports driver. | ||
| 1985 | |||
| 1977 | pcie_pme= [PCIE,PM] Native PCIe PME signaling options: | 1986 | pcie_pme= [PCIE,PM] Native PCIe PME signaling options: |
| 1978 | Format: {auto|force}[,nomsi] | ||
| 1979 | auto Use native PCIe PME signaling if the BIOS allows the | ||
| 1980 | kernel to control PCIe config registers of root ports. | ||
| 1981 | force Use native PCIe PME signaling even if the BIOS refuses | ||
| 1982 | to allow the kernel to control the relevant PCIe config | ||
| 1983 | registers. | ||
| 1984 | nomsi Do not use MSI for native PCIe PME signaling (this makes | 1987 | nomsi Do not use MSI for native PCIe PME signaling (this makes |
| 1985 | all PCIe root ports use INTx for everything). | 1988 | all PCIe root ports use INTx for all services). |
| 1986 | 1989 | ||
| 1987 | pcmv= [HW,PCMCIA] BadgePAD 4 | 1990 | pcmv= [HW,PCMCIA] BadgePAD 4 |
| 1988 | 1991 | ||
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 404a880ea325..d395540ff894 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h | |||
| @@ -27,6 +27,9 @@ extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, | |||
| 27 | int node); | 27 | int node); |
| 28 | extern struct pci_bus *pci_scan_bus_with_sysdata(int busno); | 28 | extern struct pci_bus *pci_scan_bus_with_sysdata(int busno); |
| 29 | 29 | ||
| 30 | #ifdef CONFIG_PCI | ||
| 31 | |||
| 32 | #ifdef CONFIG_PCI_DOMAINS | ||
| 30 | static inline int pci_domain_nr(struct pci_bus *bus) | 33 | static inline int pci_domain_nr(struct pci_bus *bus) |
| 31 | { | 34 | { |
| 32 | struct pci_sysdata *sd = bus->sysdata; | 35 | struct pci_sysdata *sd = bus->sysdata; |
| @@ -37,13 +40,12 @@ static inline int pci_proc_domain(struct pci_bus *bus) | |||
| 37 | { | 40 | { |
| 38 | return pci_domain_nr(bus); | 41 | return pci_domain_nr(bus); |
| 39 | } | 42 | } |
| 40 | 43 | #endif | |
| 41 | 44 | ||
| 42 | /* Can be used to override the logic in pci_scan_bus for skipping | 45 | /* Can be used to override the logic in pci_scan_bus for skipping |
| 43 | already-configured bus numbers - to be used for buggy BIOSes | 46 | already-configured bus numbers - to be used for buggy BIOSes |
| 44 | or architectures with incomplete PCI setup by the loader */ | 47 | or architectures with incomplete PCI setup by the loader */ |
| 45 | 48 | ||
| 46 | #ifdef CONFIG_PCI | ||
| 47 | extern unsigned int pcibios_assign_all_busses(void); | 49 | extern unsigned int pcibios_assign_all_busses(void); |
| 48 | extern int pci_legacy_init(void); | 50 | extern int pci_legacy_init(void); |
| 49 | # ifdef CONFIG_ACPI | 51 | # ifdef CONFIG_ACPI |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 1f67057af2a5..3ba8d1f44a73 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | #include <linux/pm_runtime.h> | 33 | #include <linux/pm_runtime.h> |
| 34 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
| 35 | #include <linux/pci-acpi.h> | 35 | #include <linux/pci-acpi.h> |
| 36 | #include <linux/pci-aspm.h> | ||
| 37 | #include <linux/acpi.h> | 36 | #include <linux/acpi.h> |
| 38 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
| 39 | #include <acpi/acpi_bus.h> | 38 | #include <acpi/acpi_bus.h> |
| @@ -226,22 +225,31 @@ static acpi_status acpi_pci_run_osc(acpi_handle handle, | |||
| 226 | return status; | 225 | return status; |
| 227 | } | 226 | } |
| 228 | 227 | ||
| 229 | static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags) | 228 | static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, |
| 229 | u32 support, | ||
| 230 | u32 *control) | ||
| 230 | { | 231 | { |
| 231 | acpi_status status; | 232 | acpi_status status; |
| 232 | u32 support_set, result, capbuf[3]; | 233 | u32 result, capbuf[3]; |
| 234 | |||
| 235 | support &= OSC_PCI_SUPPORT_MASKS; | ||
| 236 | support |= root->osc_support_set; | ||
| 233 | 237 | ||
| 234 | /* do _OSC query for all possible controls */ | ||
| 235 | support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS); | ||
| 236 | capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; | 238 | capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; |
| 237 | capbuf[OSC_SUPPORT_TYPE] = support_set; | 239 | capbuf[OSC_SUPPORT_TYPE] = support; |
| 238 | capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; | 240 | if (control) { |
| 241 | *control &= OSC_PCI_CONTROL_MASKS; | ||
| 242 | capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set; | ||
| 243 | } else { | ||
| 244 | /* Run _OSC query for all possible controls. */ | ||
| 245 | capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; | ||
| 246 | } | ||
| 239 | 247 | ||
| 240 | status = acpi_pci_run_osc(root->device->handle, capbuf, &result); | 248 | status = acpi_pci_run_osc(root->device->handle, capbuf, &result); |
| 241 | if (ACPI_SUCCESS(status)) { | 249 | if (ACPI_SUCCESS(status)) { |
| 242 | root->osc_support_set = support_set; | 250 | root->osc_support_set = support; |
| 243 | root->osc_control_qry = result; | 251 | if (control) |
| 244 | root->osc_queried = 1; | 252 | *control = result; |
| 245 | } | 253 | } |
| 246 | return status; | 254 | return status; |
| 247 | } | 255 | } |
| @@ -255,7 +263,7 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) | |||
| 255 | if (ACPI_FAILURE(status)) | 263 | if (ACPI_FAILURE(status)) |
| 256 | return status; | 264 | return status; |
| 257 | mutex_lock(&osc_lock); | 265 | mutex_lock(&osc_lock); |
| 258 | status = acpi_pci_query_osc(root, flags); | 266 | status = acpi_pci_query_osc(root, flags, NULL); |
| 259 | mutex_unlock(&osc_lock); | 267 | mutex_unlock(&osc_lock); |
| 260 | return status; | 268 | return status; |
| 261 | } | 269 | } |
| @@ -365,55 +373,70 @@ out: | |||
| 365 | EXPORT_SYMBOL_GPL(acpi_get_pci_dev); | 373 | EXPORT_SYMBOL_GPL(acpi_get_pci_dev); |
| 366 | 374 | ||
| 367 | /** | 375 | /** |
| 368 | * acpi_pci_osc_control_set - commit requested control to Firmware | 376 | * acpi_pci_osc_control_set - Request control of PCI root _OSC features. |
| 369 | * @handle: acpi_handle for the target ACPI object | 377 | * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex). |
| 370 | * @flags: driver's requested control bits | 378 | * @mask: Mask of _OSC bits to request control of, place to store control mask. |
| 379 | * @req: Mask of _OSC bits the control of is essential to the caller. | ||
| 380 | * | ||
| 381 | * Run _OSC query for @mask and if that is successful, compare the returned | ||
| 382 | * mask of control bits with @req. If all of the @req bits are set in the | ||
| 383 | * returned mask, run _OSC request for it. | ||
| 371 | * | 384 | * |
| 372 | * Attempt to take control from Firmware on requested control bits. | 385 | * The variable at the @mask address may be modified regardless of whether or |
| 386 | * not the function returns success. On success it will contain the mask of | ||
| 387 | * _OSC bits the BIOS has granted control of, but its contents are meaningless | ||
| 388 | * on failure. | ||
| 373 | **/ | 389 | **/ |
| 374 | acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) | 390 | acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req) |
| 375 | { | 391 | { |
| 392 | struct acpi_pci_root *root; | ||
| 376 | acpi_status status; | 393 | acpi_status status; |
| 377 | u32 control_req, result, capbuf[3]; | 394 | u32 ctrl, capbuf[3]; |
| 378 | acpi_handle tmp; | 395 | acpi_handle tmp; |
| 379 | struct acpi_pci_root *root; | ||
| 380 | 396 | ||
| 381 | status = acpi_get_handle(handle, "_OSC", &tmp); | 397 | if (!mask) |
| 382 | if (ACPI_FAILURE(status)) | 398 | return AE_BAD_PARAMETER; |
| 383 | return status; | ||
| 384 | 399 | ||
| 385 | control_req = (flags & OSC_PCI_CONTROL_MASKS); | 400 | ctrl = *mask & OSC_PCI_CONTROL_MASKS; |
| 386 | if (!control_req) | 401 | if ((ctrl & req) != req) |
| 387 | return AE_TYPE; | 402 | return AE_TYPE; |
| 388 | 403 | ||
| 389 | root = acpi_pci_find_root(handle); | 404 | root = acpi_pci_find_root(handle); |
| 390 | if (!root) | 405 | if (!root) |
| 391 | return AE_NOT_EXIST; | 406 | return AE_NOT_EXIST; |
| 392 | 407 | ||
| 408 | status = acpi_get_handle(handle, "_OSC", &tmp); | ||
| 409 | if (ACPI_FAILURE(status)) | ||
| 410 | return status; | ||
| 411 | |||
| 393 | mutex_lock(&osc_lock); | 412 | mutex_lock(&osc_lock); |
| 413 | |||
| 414 | *mask = ctrl | root->osc_control_set; | ||
| 394 | /* No need to evaluate _OSC if the control was already granted. */ | 415 | /* No need to evaluate _OSC if the control was already granted. */ |
| 395 | if ((root->osc_control_set & control_req) == control_req) | 416 | if ((root->osc_control_set & ctrl) == ctrl) |
| 396 | goto out; | 417 | goto out; |
| 397 | 418 | ||
| 398 | /* Need to query controls first before requesting them */ | 419 | /* Need to check the available controls bits before requesting them. */ |
| 399 | if (!root->osc_queried) { | 420 | while (*mask) { |
| 400 | status = acpi_pci_query_osc(root, root->osc_support_set); | 421 | status = acpi_pci_query_osc(root, root->osc_support_set, mask); |
| 401 | if (ACPI_FAILURE(status)) | 422 | if (ACPI_FAILURE(status)) |
| 402 | goto out; | 423 | goto out; |
| 424 | if (ctrl == *mask) | ||
| 425 | break; | ||
| 426 | ctrl = *mask; | ||
| 403 | } | 427 | } |
| 404 | if ((root->osc_control_qry & control_req) != control_req) { | 428 | |
| 405 | printk(KERN_DEBUG | 429 | if ((ctrl & req) != req) { |
| 406 | "Firmware did not grant requested _OSC control\n"); | ||
| 407 | status = AE_SUPPORT; | 430 | status = AE_SUPPORT; |
| 408 | goto out; | 431 | goto out; |
| 409 | } | 432 | } |
| 410 | 433 | ||
| 411 | capbuf[OSC_QUERY_TYPE] = 0; | 434 | capbuf[OSC_QUERY_TYPE] = 0; |
| 412 | capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; | 435 | capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; |
| 413 | capbuf[OSC_CONTROL_TYPE] = root->osc_control_set | control_req; | 436 | capbuf[OSC_CONTROL_TYPE] = ctrl; |
| 414 | status = acpi_pci_run_osc(handle, capbuf, &result); | 437 | status = acpi_pci_run_osc(handle, capbuf, mask); |
| 415 | if (ACPI_SUCCESS(status)) | 438 | if (ACPI_SUCCESS(status)) |
| 416 | root->osc_control_set = result; | 439 | root->osc_control_set = *mask; |
| 417 | out: | 440 | out: |
| 418 | mutex_unlock(&osc_lock); | 441 | mutex_unlock(&osc_lock); |
| 419 | return status; | 442 | return status; |
| @@ -544,14 +567,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 544 | if (flags != base_flags) | 567 | if (flags != base_flags) |
| 545 | acpi_pci_osc_support(root, flags); | 568 | acpi_pci_osc_support(root, flags); |
| 546 | 569 | ||
| 547 | status = acpi_pci_osc_control_set(root->device->handle, | ||
| 548 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | ||
| 549 | |||
| 550 | if (ACPI_FAILURE(status)) { | ||
| 551 | printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n"); | ||
| 552 | pcie_no_aspm(); | ||
| 553 | } | ||
| 554 | |||
| 555 | pci_acpi_add_bus_pm_notifier(device, root->bus); | 570 | pci_acpi_add_bus_pm_notifier(device, root->bus); |
| 556 | if (device->wakeup.flags.run_wake) | 571 | if (device->wakeup.flags.run_wake) |
| 557 | device_set_run_wake(root->bus->bridge, true); | 572 | device_set_run_wake(root->bus->bridge, true); |
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 45fcc1e96df9..3bc72d18b121 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
| @@ -338,9 +338,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) | |||
| 338 | acpi_handle chandle, handle; | 338 | acpi_handle chandle, handle; |
| 339 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | 339 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 340 | 340 | ||
| 341 | flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | | 341 | flags &= OSC_SHPC_NATIVE_HP_CONTROL; |
| 342 | OSC_SHPC_NATIVE_HP_CONTROL | | ||
| 343 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | ||
| 344 | if (!flags) { | 342 | if (!flags) { |
| 345 | err("Invalid flags %u specified!\n", flags); | 343 | err("Invalid flags %u specified!\n", flags); |
| 346 | return -EINVAL; | 344 | return -EINVAL; |
| @@ -360,7 +358,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) | |||
| 360 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | 358 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); |
| 361 | dbg("Trying to get hotplug control for %s\n", | 359 | dbg("Trying to get hotplug control for %s\n", |
| 362 | (char *)string.pointer); | 360 | (char *)string.pointer); |
| 363 | status = acpi_pci_osc_control_set(handle, flags); | 361 | status = acpi_pci_osc_control_set(handle, &flags, flags); |
| 364 | if (ACPI_SUCCESS(status)) | 362 | if (ACPI_SUCCESS(status)) |
| 365 | goto got_one; | 363 | goto got_one; |
| 366 | if (status == AE_SUPPORT) | 364 | if (status == AE_SUPPORT) |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 4ed76b47b6dc..73d513989263 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
| @@ -176,19 +176,11 @@ static inline void pciehp_firmware_init(void) | |||
| 176 | { | 176 | { |
| 177 | pciehp_acpi_slot_detection_init(); | 177 | pciehp_acpi_slot_detection_init(); |
| 178 | } | 178 | } |
| 179 | |||
| 180 | static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) | ||
| 181 | { | ||
| 182 | int retval; | ||
| 183 | u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | | ||
| 184 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | ||
| 185 | retval = acpi_get_hp_hw_control_from_firmware(dev, flags); | ||
| 186 | if (retval) | ||
| 187 | return retval; | ||
| 188 | return pciehp_acpi_slot_detection_check(dev); | ||
| 189 | } | ||
| 190 | #else | 179 | #else |
| 191 | #define pciehp_firmware_init() do {} while (0) | 180 | #define pciehp_firmware_init() do {} while (0) |
| 192 | #define pciehp_get_hp_hw_control_from_firmware(dev) 0 | 181 | static inline int pciehp_acpi_slot_detection_check(struct pci_dev *dev) |
| 182 | { | ||
| 183 | return 0; | ||
| 184 | } | ||
| 193 | #endif /* CONFIG_ACPI */ | 185 | #endif /* CONFIG_ACPI */ |
| 194 | #endif /* _PCIEHP_H */ | 186 | #endif /* _PCIEHP_H */ |
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index 1f4000a5a108..2574700db461 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c | |||
| @@ -85,9 +85,7 @@ static int __init dummy_probe(struct pcie_device *dev) | |||
| 85 | acpi_handle handle; | 85 | acpi_handle handle; |
| 86 | struct dummy_slot *slot, *tmp; | 86 | struct dummy_slot *slot, *tmp; |
| 87 | struct pci_dev *pdev = dev->port; | 87 | struct pci_dev *pdev = dev->port; |
| 88 | /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ | 88 | |
| 89 | if (pciehp_get_hp_hw_control_from_firmware(pdev)) | ||
| 90 | return -ENODEV; | ||
| 91 | pos = pci_pcie_cap(pdev); | 89 | pos = pci_pcie_cap(pdev); |
| 92 | if (!pos) | 90 | if (!pos) |
| 93 | return -ENODEV; | 91 | return -ENODEV; |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 3588ea61b0dd..aa5f3ff629ff 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
| @@ -59,7 +59,7 @@ module_param(pciehp_force, bool, 0644); | |||
| 59 | MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); | 59 | MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); |
| 60 | MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); | 60 | MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); |
| 61 | MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); | 61 | MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); |
| 62 | MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"); | 62 | MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if OSHP is missing"); |
| 63 | 63 | ||
| 64 | #define PCIE_MODULE_NAME "pciehp" | 64 | #define PCIE_MODULE_NAME "pciehp" |
| 65 | 65 | ||
| @@ -235,7 +235,7 @@ static int pciehp_probe(struct pcie_device *dev) | |||
| 235 | dev_info(&dev->device, | 235 | dev_info(&dev->device, |
| 236 | "Bypassing BIOS check for pciehp use on %s\n", | 236 | "Bypassing BIOS check for pciehp use on %s\n", |
| 237 | pci_name(dev->port)); | 237 | pci_name(dev->port)); |
| 238 | else if (pciehp_get_hp_hw_control_from_firmware(dev->port)) | 238 | else if (pciehp_acpi_slot_detection_check(dev->port)) |
| 239 | goto err_out_none; | 239 | goto err_out_none; |
| 240 | 240 | ||
| 241 | ctrl = pcie_init(dev); | 241 | ctrl = pcie_init(dev); |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 679c39de6a89..7754a678ab15 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
| @@ -140,8 +140,10 @@ static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } | |||
| 140 | 140 | ||
| 141 | #ifdef CONFIG_PCIEAER | 141 | #ifdef CONFIG_PCIEAER |
| 142 | void pci_no_aer(void); | 142 | void pci_no_aer(void); |
| 143 | bool pci_aer_available(void); | ||
| 143 | #else | 144 | #else |
| 144 | static inline void pci_no_aer(void) { } | 145 | static inline void pci_no_aer(void) { } |
| 146 | static inline bool pci_aer_available(void) { return false; } | ||
| 145 | #endif | 147 | #endif |
| 146 | 148 | ||
| 147 | static inline int pci_no_d1d2(struct pci_dev *dev) | 149 | static inline int pci_no_d1d2(struct pci_dev *dev) |
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile index ea654545e7c4..00c62df5a9fc 100644 --- a/drivers/pci/pcie/Makefile +++ b/drivers/pci/pcie/Makefile | |||
| @@ -6,10 +6,11 @@ | |||
| 6 | obj-$(CONFIG_PCIEASPM) += aspm.o | 6 | obj-$(CONFIG_PCIEASPM) += aspm.o |
| 7 | 7 | ||
| 8 | pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o | 8 | pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o |
| 9 | pcieportdrv-$(CONFIG_ACPI) += portdrv_acpi.o | ||
| 9 | 10 | ||
| 10 | obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o | 11 | obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o |
| 11 | 12 | ||
| 12 | # Build PCI Express AER if needed | 13 | # Build PCI Express AER if needed |
| 13 | obj-$(CONFIG_PCIEAER) += aer/ | 14 | obj-$(CONFIG_PCIEAER) += aer/ |
| 14 | 15 | ||
| 15 | obj-$(CONFIG_PCIE_PME) += pme/ | 16 | obj-$(CONFIG_PCIE_PME) += pme.o |
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 484cc55194b8..f409948e1a9b 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c | |||
| @@ -72,6 +72,11 @@ void pci_no_aer(void) | |||
| 72 | pcie_aer_disable = 1; /* has priority over 'forceload' */ | 72 | pcie_aer_disable = 1; /* has priority over 'forceload' */ |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | bool pci_aer_available(void) | ||
| 76 | { | ||
| 77 | return !pcie_aer_disable && pci_msi_enabled(); | ||
| 78 | } | ||
| 79 | |||
| 75 | static int set_device_error_reporting(struct pci_dev *dev, void *data) | 80 | static int set_device_error_reporting(struct pci_dev *dev, void *data) |
| 76 | { | 81 | { |
| 77 | bool enable = *((bool *)data); | 82 | bool enable = *((bool *)data); |
| @@ -411,9 +416,7 @@ static void aer_error_resume(struct pci_dev *dev) | |||
| 411 | */ | 416 | */ |
| 412 | static int __init aer_service_init(void) | 417 | static int __init aer_service_init(void) |
| 413 | { | 418 | { |
| 414 | if (pcie_aer_disable) | 419 | if (!pci_aer_available()) |
| 415 | return -ENXIO; | ||
| 416 | if (!pci_msi_enabled()) | ||
| 417 | return -ENXIO; | 420 | return -ENXIO; |
| 418 | return pcie_port_service_register(&aerdriver); | 421 | return pcie_port_service_register(&aerdriver); |
| 419 | } | 422 | } |
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index f278d7b0d95d..2bb9b8972211 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c | |||
| @@ -19,42 +19,6 @@ | |||
| 19 | #include <acpi/apei.h> | 19 | #include <acpi/apei.h> |
| 20 | #include "aerdrv.h" | 20 | #include "aerdrv.h" |
| 21 | 21 | ||
| 22 | /** | ||
| 23 | * aer_osc_setup - run ACPI _OSC method | ||
| 24 | * @pciedev: pcie_device which AER is being enabled on | ||
| 25 | * | ||
| 26 | * @return: Zero on success. Nonzero otherwise. | ||
| 27 | * | ||
| 28 | * Invoked when PCIe bus loads AER service driver. To avoid conflict with | ||
| 29 | * BIOS AER support requires BIOS to yield AER control to OS native driver. | ||
| 30 | **/ | ||
| 31 | int aer_osc_setup(struct pcie_device *pciedev) | ||
| 32 | { | ||
| 33 | acpi_status status = AE_NOT_FOUND; | ||
| 34 | struct pci_dev *pdev = pciedev->port; | ||
| 35 | acpi_handle handle = NULL; | ||
| 36 | |||
| 37 | if (acpi_pci_disabled) | ||
| 38 | return -1; | ||
| 39 | |||
| 40 | handle = acpi_find_root_bridge_handle(pdev); | ||
| 41 | if (handle) { | ||
| 42 | status = acpi_pci_osc_control_set(handle, | ||
| 43 | OSC_PCI_EXPRESS_AER_CONTROL | | ||
| 44 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | ||
| 45 | } | ||
| 46 | |||
| 47 | if (ACPI_FAILURE(status)) { | ||
| 48 | dev_printk(KERN_DEBUG, &pciedev->device, "AER service couldn't " | ||
| 49 | "init device: %s\n", | ||
| 50 | (status == AE_SUPPORT || status == AE_NOT_FOUND) ? | ||
| 51 | "no _OSC support" : "_OSC failed"); | ||
| 52 | return -1; | ||
| 53 | } | ||
| 54 | |||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | |||
| 58 | #ifdef CONFIG_ACPI_APEI | 22 | #ifdef CONFIG_ACPI_APEI |
| 59 | static inline int hest_match_pci(struct acpi_hest_aer_common *p, | 23 | static inline int hest_match_pci(struct acpi_hest_aer_common *p, |
| 60 | struct pci_dev *pci) | 24 | struct pci_dev *pci) |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index fc0b5a93e1de..29e268fadf14 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
| @@ -772,22 +772,10 @@ void aer_isr(struct work_struct *work) | |||
| 772 | */ | 772 | */ |
| 773 | int aer_init(struct pcie_device *dev) | 773 | int aer_init(struct pcie_device *dev) |
| 774 | { | 774 | { |
| 775 | if (pcie_aer_get_firmware_first(dev->port)) { | ||
| 776 | dev_printk(KERN_DEBUG, &dev->device, | ||
| 777 | "PCIe errors handled by platform firmware.\n"); | ||
| 778 | goto out; | ||
| 779 | } | ||
| 780 | |||
| 781 | if (aer_osc_setup(dev)) | ||
| 782 | goto out; | ||
| 783 | |||
| 784 | return 0; | ||
| 785 | out: | ||
| 786 | if (forceload) { | 775 | if (forceload) { |
| 787 | dev_printk(KERN_DEBUG, &dev->device, | 776 | dev_printk(KERN_DEBUG, &dev->device, |
| 788 | "aerdrv forceload requested.\n"); | 777 | "aerdrv forceload requested.\n"); |
| 789 | pcie_aer_force_firmware_first(dev->port, 0); | 778 | pcie_aer_force_firmware_first(dev->port, 0); |
| 790 | return 0; | ||
| 791 | } | 779 | } |
| 792 | return -ENXIO; | 780 | return 0; |
| 793 | } | 781 | } |
diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme.c index bbdea18693d9..2f3c90407227 100644 --- a/drivers/pci/pcie/pme/pcie_pme.c +++ b/drivers/pci/pcie/pme.c | |||
| @@ -23,38 +23,13 @@ | |||
| 23 | #include <linux/pci-acpi.h> | 23 | #include <linux/pci-acpi.h> |
| 24 | #include <linux/pm_runtime.h> | 24 | #include <linux/pm_runtime.h> |
| 25 | 25 | ||
| 26 | #include "../../pci.h" | 26 | #include "../pci.h" |
| 27 | #include "pcie_pme.h" | 27 | #include "portdrv.h" |
| 28 | 28 | ||
| 29 | #define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ | 29 | #define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ |
| 30 | #define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ | 30 | #define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ |
| 31 | 31 | ||
| 32 | /* | 32 | /* |
| 33 | * If set, this switch will prevent the PCIe root port PME service driver from | ||
| 34 | * being registered. Consequently, the interrupt-based PCIe PME signaling will | ||
| 35 | * not be used by any PCIe root ports in that case. | ||
| 36 | */ | ||
| 37 | static bool pcie_pme_disabled = true; | ||
| 38 | |||
| 39 | /* | ||
| 40 | * The PCI Express Base Specification 2.0, Section 6.1.8, states the following: | ||
| 41 | * "In order to maintain compatibility with non-PCI Express-aware system | ||
| 42 | * software, system power management logic must be configured by firmware to use | ||
| 43 | * the legacy mechanism of signaling PME by default. PCI Express-aware system | ||
| 44 | * software must notify the firmware prior to enabling native, interrupt-based | ||
| 45 | * PME signaling." However, if the platform doesn't provide us with a suitable | ||
| 46 | * notification mechanism or the notification fails, it is not clear whether or | ||
| 47 | * not we are supposed to use the interrupt-based PCIe PME signaling. The | ||
| 48 | * switch below can be used to indicate the desired behaviour. When set, it | ||
| 49 | * will make the kernel use the interrupt-based PCIe PME signaling regardless of | ||
| 50 | * the platform notification status, although the kernel will attempt to notify | ||
| 51 | * the platform anyway. When unset, it will prevent the kernel from using the | ||
| 52 | * the interrupt-based PCIe PME signaling if the platform notification fails, | ||
| 53 | * which is the default. | ||
| 54 | */ | ||
| 55 | static bool pcie_pme_force_enable; | ||
| 56 | |||
| 57 | /* | ||
| 58 | * If this switch is set, MSI will not be used for PCIe PME signaling. This | 33 | * If this switch is set, MSI will not be used for PCIe PME signaling. This |
| 59 | * causes the PCIe port driver to use INTx interrupts only, but it turns out | 34 | * causes the PCIe port driver to use INTx interrupts only, but it turns out |
| 60 | * that using MSI for PCIe PME signaling doesn't play well with PCIe PME-based | 35 | * that using MSI for PCIe PME signaling doesn't play well with PCIe PME-based |
| @@ -64,38 +39,13 @@ bool pcie_pme_msi_disabled; | |||
| 64 | 39 | ||
| 65 | static int __init pcie_pme_setup(char *str) | 40 | static int __init pcie_pme_setup(char *str) |
| 66 | { | 41 | { |
| 67 | if (!strncmp(str, "auto", 4)) | 42 | if (!strncmp(str, "nomsi", 5)) |
| 68 | pcie_pme_disabled = false; | 43 | pcie_pme_msi_disabled = true; |
| 69 | else if (!strncmp(str, "force", 5)) | ||
| 70 | pcie_pme_force_enable = true; | ||
| 71 | |||
| 72 | str = strchr(str, ','); | ||
| 73 | if (str) { | ||
| 74 | str++; | ||
| 75 | str += strspn(str, " \t"); | ||
| 76 | if (*str && !strcmp(str, "nomsi")) | ||
| 77 | pcie_pme_msi_disabled = true; | ||
| 78 | } | ||
| 79 | 44 | ||
| 80 | return 1; | 45 | return 1; |
| 81 | } | 46 | } |
| 82 | __setup("pcie_pme=", pcie_pme_setup); | 47 | __setup("pcie_pme=", pcie_pme_setup); |
| 83 | 48 | ||
| 84 | /** | ||
| 85 | * pcie_pme_platform_setup - Ensure that the kernel controls the PCIe PME. | ||
| 86 | * @srv: PCIe PME root port service to use for carrying out the check. | ||
| 87 | * | ||
| 88 | * Notify the platform that the native PCIe PME is going to be used and return | ||
| 89 | * 'true' if the control of the PCIe PME registers has been acquired from the | ||
| 90 | * platform. | ||
| 91 | */ | ||
| 92 | static bool pcie_pme_platform_setup(struct pcie_device *srv) | ||
| 93 | { | ||
| 94 | if (!pcie_pme_platform_notify(srv)) | ||
| 95 | return true; | ||
| 96 | return pcie_pme_force_enable; | ||
| 97 | } | ||
| 98 | |||
| 99 | struct pcie_pme_service_data { | 49 | struct pcie_pme_service_data { |
| 100 | spinlock_t lock; | 50 | spinlock_t lock; |
| 101 | struct pcie_device *srv; | 51 | struct pcie_device *srv; |
| @@ -108,7 +58,7 @@ struct pcie_pme_service_data { | |||
| 108 | * @dev: PCIe root port or event collector. | 58 | * @dev: PCIe root port or event collector. |
| 109 | * @enable: Enable or disable the interrupt. | 59 | * @enable: Enable or disable the interrupt. |
| 110 | */ | 60 | */ |
| 111 | static void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) | 61 | void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) |
| 112 | { | 62 | { |
| 113 | int rtctl_pos; | 63 | int rtctl_pos; |
| 114 | u16 rtctl; | 64 | u16 rtctl; |
| @@ -417,9 +367,6 @@ static int pcie_pme_probe(struct pcie_device *srv) | |||
| 417 | struct pcie_pme_service_data *data; | 367 | struct pcie_pme_service_data *data; |
| 418 | int ret; | 368 | int ret; |
| 419 | 369 | ||
| 420 | if (!pcie_pme_platform_setup(srv)) | ||
| 421 | return -EACCES; | ||
| 422 | |||
| 423 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 370 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
| 424 | if (!data) | 371 | if (!data) |
| 425 | return -ENOMEM; | 372 | return -ENOMEM; |
| @@ -509,8 +456,7 @@ static struct pcie_port_service_driver pcie_pme_driver = { | |||
| 509 | */ | 456 | */ |
| 510 | static int __init pcie_pme_service_init(void) | 457 | static int __init pcie_pme_service_init(void) |
| 511 | { | 458 | { |
| 512 | return pcie_pme_disabled ? | 459 | return pcie_port_service_register(&pcie_pme_driver); |
| 513 | -ENODEV : pcie_port_service_register(&pcie_pme_driver); | ||
| 514 | } | 460 | } |
| 515 | 461 | ||
| 516 | module_init(pcie_pme_service_init); | 462 | module_init(pcie_pme_service_init); |
diff --git a/drivers/pci/pcie/pme/Makefile b/drivers/pci/pcie/pme/Makefile deleted file mode 100644 index 8b9238053080..000000000000 --- a/drivers/pci/pcie/pme/Makefile +++ /dev/null | |||
| @@ -1,8 +0,0 @@ | |||
| 1 | # | ||
| 2 | # Makefile for PCI-Express Root Port PME signaling driver | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_PCIE_PME) += pmedriver.o | ||
| 6 | |||
| 7 | pmedriver-objs := pcie_pme.o | ||
| 8 | pmedriver-$(CONFIG_ACPI) += pcie_pme_acpi.o | ||
diff --git a/drivers/pci/pcie/pme/pcie_pme.h b/drivers/pci/pcie/pme/pcie_pme.h deleted file mode 100644 index b30d2b7c9775..000000000000 --- a/drivers/pci/pcie/pme/pcie_pme.h +++ /dev/null | |||
| @@ -1,28 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * drivers/pci/pcie/pme/pcie_pme.h | ||
| 3 | * | ||
| 4 | * PCI Express Root Port PME signaling support | ||
| 5 | * | ||
| 6 | * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef _PCIE_PME_H_ | ||
| 10 | #define _PCIE_PME_H_ | ||
| 11 | |||
| 12 | struct pcie_device; | ||
| 13 | |||
| 14 | #ifdef CONFIG_ACPI | ||
| 15 | extern int pcie_pme_acpi_setup(struct pcie_device *srv); | ||
| 16 | |||
| 17 | static inline int pcie_pme_platform_notify(struct pcie_device *srv) | ||
| 18 | { | ||
| 19 | return pcie_pme_acpi_setup(srv); | ||
| 20 | } | ||
| 21 | #else /* !CONFIG_ACPI */ | ||
| 22 | static inline int pcie_pme_platform_notify(struct pcie_device *srv) | ||
| 23 | { | ||
| 24 | return 0; | ||
| 25 | } | ||
| 26 | #endif /* !CONFIG_ACPI */ | ||
| 27 | |||
| 28 | #endif | ||
diff --git a/drivers/pci/pcie/pme/pcie_pme_acpi.c b/drivers/pci/pcie/pme/pcie_pme_acpi.c deleted file mode 100644 index 83ab2287ae3f..000000000000 --- a/drivers/pci/pcie/pme/pcie_pme_acpi.c +++ /dev/null | |||
| @@ -1,54 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * PCIe Native PME support, ACPI-related part | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
| 5 | * | ||
| 6 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 7 | * License V2. See the file "COPYING" in the main directory of this archive | ||
| 8 | * for more details. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/pci.h> | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/errno.h> | ||
| 14 | #include <linux/acpi.h> | ||
| 15 | #include <linux/pci-acpi.h> | ||
| 16 | #include <linux/pcieport_if.h> | ||
| 17 | |||
| 18 | /** | ||
| 19 | * pcie_pme_acpi_setup - Request the ACPI BIOS to release control over PCIe PME. | ||
| 20 | * @srv - PCIe PME service for a root port or event collector. | ||
| 21 | * | ||
| 22 | * Invoked when the PCIe bus type loads PCIe PME service driver. To avoid | ||
| 23 | * conflict with the BIOS PCIe support requires the BIOS to yield PCIe PME | ||
| 24 | * control to the kernel. | ||
| 25 | */ | ||
| 26 | int pcie_pme_acpi_setup(struct pcie_device *srv) | ||
| 27 | { | ||
| 28 | acpi_status status = AE_NOT_FOUND; | ||
| 29 | struct pci_dev *port = srv->port; | ||
| 30 | acpi_handle handle; | ||
| 31 | int error = 0; | ||
| 32 | |||
| 33 | if (acpi_pci_disabled) | ||
| 34 | return -ENOSYS; | ||
| 35 | |||
| 36 | dev_info(&port->dev, "Requesting control of PCIe PME from ACPI BIOS\n"); | ||
| 37 | |||
| 38 | handle = acpi_find_root_bridge_handle(port); | ||
| 39 | if (!handle) | ||
| 40 | return -EINVAL; | ||
| 41 | |||
| 42 | status = acpi_pci_osc_control_set(handle, | ||
| 43 | OSC_PCI_EXPRESS_PME_CONTROL | | ||
| 44 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | ||
| 45 | if (ACPI_FAILURE(status)) { | ||
| 46 | dev_info(&port->dev, | ||
| 47 | "Failed to receive control of PCIe PME service: %s\n", | ||
| 48 | (status == AE_SUPPORT || status == AE_NOT_FOUND) ? | ||
| 49 | "no _OSC support" : "ACPI _OSC failed"); | ||
| 50 | error = -ENODEV; | ||
| 51 | } | ||
| 52 | |||
| 53 | return error; | ||
| 54 | } | ||
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 813a5c3427b6..7b5aba0a3291 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h | |||
| @@ -20,6 +20,9 @@ | |||
| 20 | 20 | ||
| 21 | #define get_descriptor_id(type, service) (((type - 4) << 4) | service) | 21 | #define get_descriptor_id(type, service) (((type - 4) << 4) | service) |
| 22 | 22 | ||
| 23 | extern bool pcie_ports_disabled; | ||
| 24 | extern bool pcie_ports_auto; | ||
| 25 | |||
| 23 | extern struct bus_type pcie_port_bus_type; | 26 | extern struct bus_type pcie_port_bus_type; |
| 24 | extern int pcie_port_device_register(struct pci_dev *dev); | 27 | extern int pcie_port_device_register(struct pci_dev *dev); |
| 25 | #ifdef CONFIG_PM | 28 | #ifdef CONFIG_PM |
| @@ -30,6 +33,8 @@ extern void pcie_port_device_remove(struct pci_dev *dev); | |||
| 30 | extern int __must_check pcie_port_bus_register(void); | 33 | extern int __must_check pcie_port_bus_register(void); |
| 31 | extern void pcie_port_bus_unregister(void); | 34 | extern void pcie_port_bus_unregister(void); |
| 32 | 35 | ||
| 36 | struct pci_dev; | ||
| 37 | |||
| 33 | #ifdef CONFIG_PCIE_PME | 38 | #ifdef CONFIG_PCIE_PME |
| 34 | extern bool pcie_pme_msi_disabled; | 39 | extern bool pcie_pme_msi_disabled; |
| 35 | 40 | ||
| @@ -42,9 +47,26 @@ static inline bool pcie_pme_no_msi(void) | |||
| 42 | { | 47 | { |
| 43 | return pcie_pme_msi_disabled; | 48 | return pcie_pme_msi_disabled; |
| 44 | } | 49 | } |
| 50 | |||
| 51 | extern void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable); | ||
| 45 | #else /* !CONFIG_PCIE_PME */ | 52 | #else /* !CONFIG_PCIE_PME */ |
| 46 | static inline void pcie_pme_disable_msi(void) {} | 53 | static inline void pcie_pme_disable_msi(void) {} |
| 47 | static inline bool pcie_pme_no_msi(void) { return false; } | 54 | static inline bool pcie_pme_no_msi(void) { return false; } |
| 55 | static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {} | ||
| 48 | #endif /* !CONFIG_PCIE_PME */ | 56 | #endif /* !CONFIG_PCIE_PME */ |
| 49 | 57 | ||
| 58 | #ifdef CONFIG_ACPI | ||
| 59 | extern int pcie_port_acpi_setup(struct pci_dev *port, int *mask); | ||
| 60 | |||
| 61 | static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask) | ||
| 62 | { | ||
| 63 | return pcie_port_acpi_setup(port, mask); | ||
| 64 | } | ||
| 65 | #else /* !CONFIG_ACPI */ | ||
| 66 | static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask) | ||
| 67 | { | ||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | #endif /* !CONFIG_ACPI */ | ||
| 71 | |||
| 50 | #endif /* _PORTDRV_H_ */ | 72 | #endif /* _PORTDRV_H_ */ |
diff --git a/drivers/pci/pcie/portdrv_acpi.c b/drivers/pci/pcie/portdrv_acpi.c new file mode 100644 index 000000000000..b7c4cb1ccb23 --- /dev/null +++ b/drivers/pci/pcie/portdrv_acpi.c | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | /* | ||
| 2 | * PCIe Port Native Services Support, ACPI-Related Part | ||
| 3 | * | ||
| 4 | * Copyright (C) 2010 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
| 5 | * | ||
| 6 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 7 | * License V2. See the file "COPYING" in the main directory of this archive | ||
| 8 | * for more details. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/pci.h> | ||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/errno.h> | ||
| 14 | #include <linux/acpi.h> | ||
| 15 | #include <linux/pci-acpi.h> | ||
| 16 | #include <linux/pcieport_if.h> | ||
| 17 | |||
| 18 | #include "aer/aerdrv.h" | ||
| 19 | #include "../pci.h" | ||
| 20 | |||
| 21 | /** | ||
| 22 | * pcie_port_acpi_setup - Request the BIOS to release control of PCIe services. | ||
| 23 | * @port: PCIe Port service for a root port or event collector. | ||
| 24 | * @srv_mask: Bit mask of services that can be enabled for @port. | ||
| 25 | * | ||
| 26 | * Invoked when @port is identified as a PCIe port device. To avoid conflicts | ||
| 27 | * with the BIOS PCIe port native services support requires the BIOS to yield | ||
| 28 | * control of these services to the kernel. The mask of services that the BIOS | ||
| 29 | * allows to be enabled for @port is written to @srv_mask. | ||
| 30 | * | ||
| 31 | * NOTE: It turns out that we cannot do that for individual port services | ||
| 32 | * separately, because that would make some systems work incorrectly. | ||
| 33 | */ | ||
| 34 | int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask) | ||
| 35 | { | ||
| 36 | acpi_status status; | ||
| 37 | acpi_handle handle; | ||
| 38 | u32 flags; | ||
| 39 | |||
| 40 | if (acpi_pci_disabled) | ||
| 41 | return 0; | ||
| 42 | |||
| 43 | handle = acpi_find_root_bridge_handle(port); | ||
| 44 | if (!handle) | ||
| 45 | return -EINVAL; | ||
| 46 | |||
| 47 | flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL | ||
| 48 | | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | ||
| 49 | | OSC_PCI_EXPRESS_PME_CONTROL; | ||
| 50 | |||
| 51 | if (pci_aer_available()) { | ||
| 52 | if (pcie_aer_get_firmware_first(port)) | ||
| 53 | dev_dbg(&port->dev, "PCIe errors handled by BIOS.\n"); | ||
| 54 | else | ||
| 55 | flags |= OSC_PCI_EXPRESS_AER_CONTROL; | ||
| 56 | } | ||
| 57 | |||
| 58 | status = acpi_pci_osc_control_set(handle, &flags, | ||
| 59 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | ||
| 60 | if (ACPI_FAILURE(status)) { | ||
| 61 | dev_dbg(&port->dev, "ACPI _OSC request failed (code %d)\n", | ||
| 62 | status); | ||
| 63 | return -ENODEV; | ||
| 64 | } | ||
| 65 | |||
| 66 | dev_info(&port->dev, "ACPI _OSC control granted for 0x%02x\n", flags); | ||
| 67 | |||
| 68 | *srv_mask = PCIE_PORT_SERVICE_VC; | ||
| 69 | if (flags & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL) | ||
| 70 | *srv_mask |= PCIE_PORT_SERVICE_HP; | ||
| 71 | if (flags & OSC_PCI_EXPRESS_PME_CONTROL) | ||
| 72 | *srv_mask |= PCIE_PORT_SERVICE_PME; | ||
| 73 | if (flags & OSC_PCI_EXPRESS_AER_CONTROL) | ||
| 74 | *srv_mask |= PCIE_PORT_SERVICE_AER; | ||
| 75 | |||
| 76 | return 0; | ||
| 77 | } | ||
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index e73effbe402c..a9c222d79ebc 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | #include <linux/string.h> | 14 | #include <linux/string.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/pcieport_if.h> | 16 | #include <linux/pcieport_if.h> |
| 17 | #include <linux/aer.h> | ||
| 18 | #include <linux/pci-aspm.h> | ||
| 17 | 19 | ||
| 18 | #include "../pci.h" | 20 | #include "../pci.h" |
| 19 | #include "portdrv.h" | 21 | #include "portdrv.h" |
| @@ -236,24 +238,64 @@ static int get_port_device_capability(struct pci_dev *dev) | |||
| 236 | int services = 0, pos; | 238 | int services = 0, pos; |
| 237 | u16 reg16; | 239 | u16 reg16; |
| 238 | u32 reg32; | 240 | u32 reg32; |
| 241 | int cap_mask; | ||
| 242 | int err; | ||
| 243 | |||
| 244 | err = pcie_port_platform_notify(dev, &cap_mask); | ||
| 245 | if (pcie_ports_auto) { | ||
| 246 | if (err) { | ||
| 247 | pcie_no_aspm(); | ||
| 248 | return 0; | ||
| 249 | } | ||
| 250 | } else { | ||
| 251 | cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP | ||
| 252 | | PCIE_PORT_SERVICE_VC; | ||
| 253 | if (pci_aer_available()) | ||
| 254 | cap_mask |= PCIE_PORT_SERVICE_AER; | ||
| 255 | } | ||
| 239 | 256 | ||
| 240 | pos = pci_pcie_cap(dev); | 257 | pos = pci_pcie_cap(dev); |
| 241 | pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); | 258 | pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); |
| 242 | /* Hot-Plug Capable */ | 259 | /* Hot-Plug Capable */ |
| 243 | if (reg16 & PCI_EXP_FLAGS_SLOT) { | 260 | if ((cap_mask & PCIE_PORT_SERVICE_HP) && (reg16 & PCI_EXP_FLAGS_SLOT)) { |
| 244 | pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, ®32); | 261 | pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, ®32); |
| 245 | if (reg32 & PCI_EXP_SLTCAP_HPC) | 262 | if (reg32 & PCI_EXP_SLTCAP_HPC) { |
| 246 | services |= PCIE_PORT_SERVICE_HP; | 263 | services |= PCIE_PORT_SERVICE_HP; |
| 264 | /* | ||
| 265 | * Disable hot-plug interrupts in case they have been | ||
| 266 | * enabled by the BIOS and the hot-plug service driver | ||
| 267 | * is not loaded. | ||
| 268 | */ | ||
| 269 | pos += PCI_EXP_SLTCTL; | ||
| 270 | pci_read_config_word(dev, pos, ®16); | ||
| 271 | reg16 &= ~(PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE); | ||
| 272 | pci_write_config_word(dev, pos, reg16); | ||
| 273 | } | ||
| 247 | } | 274 | } |
| 248 | /* AER capable */ | 275 | /* AER capable */ |
| 249 | if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) | 276 | if ((cap_mask & PCIE_PORT_SERVICE_AER) |
| 277 | && pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) { | ||
| 250 | services |= PCIE_PORT_SERVICE_AER; | 278 | services |= PCIE_PORT_SERVICE_AER; |
| 279 | /* | ||
| 280 | * Disable AER on this port in case it's been enabled by the | ||
| 281 | * BIOS (the AER service driver will enable it when necessary). | ||
| 282 | */ | ||
| 283 | pci_disable_pcie_error_reporting(dev); | ||
| 284 | } | ||
| 251 | /* VC support */ | 285 | /* VC support */ |
| 252 | if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC)) | 286 | if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC)) |
| 253 | services |= PCIE_PORT_SERVICE_VC; | 287 | services |= PCIE_PORT_SERVICE_VC; |
| 254 | /* Root ports are capable of generating PME too */ | 288 | /* Root ports are capable of generating PME too */ |
| 255 | if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) | 289 | if ((cap_mask & PCIE_PORT_SERVICE_PME) |
| 290 | && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) { | ||
| 256 | services |= PCIE_PORT_SERVICE_PME; | 291 | services |= PCIE_PORT_SERVICE_PME; |
| 292 | /* | ||
| 293 | * Disable PME interrupt on this port in case it's been enabled | ||
| 294 | * by the BIOS (the PME service driver will enable it when | ||
| 295 | * necessary). | ||
| 296 | */ | ||
| 297 | pcie_pme_interrupt_enable(dev, false); | ||
| 298 | } | ||
| 257 | 299 | ||
| 258 | return services; | 300 | return services; |
| 259 | } | 301 | } |
| @@ -494,6 +536,9 @@ static void pcie_port_shutdown_service(struct device *dev) {} | |||
| 494 | */ | 536 | */ |
| 495 | int pcie_port_service_register(struct pcie_port_service_driver *new) | 537 | int pcie_port_service_register(struct pcie_port_service_driver *new) |
| 496 | { | 538 | { |
| 539 | if (pcie_ports_disabled) | ||
| 540 | return -ENODEV; | ||
| 541 | |||
| 497 | new->driver.name = (char *)new->name; | 542 | new->driver.name = (char *)new->name; |
| 498 | new->driver.bus = &pcie_port_bus_type; | 543 | new->driver.bus = &pcie_port_bus_type; |
| 499 | new->driver.probe = pcie_port_probe_service; | 544 | new->driver.probe = pcie_port_probe_service; |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 3debed25e46b..f9033e190fb6 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/pcieport_if.h> | 15 | #include <linux/pcieport_if.h> |
| 16 | #include <linux/aer.h> | 16 | #include <linux/aer.h> |
| 17 | #include <linux/dmi.h> | 17 | #include <linux/dmi.h> |
| 18 | #include <linux/pci-aspm.h> | ||
| 18 | 19 | ||
| 19 | #include "portdrv.h" | 20 | #include "portdrv.h" |
| 20 | #include "aer/aerdrv.h" | 21 | #include "aer/aerdrv.h" |
| @@ -29,6 +30,31 @@ MODULE_AUTHOR(DRIVER_AUTHOR); | |||
| 29 | MODULE_DESCRIPTION(DRIVER_DESC); | 30 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 30 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
| 31 | 32 | ||
| 33 | /* If this switch is set, PCIe port native services should not be enabled. */ | ||
| 34 | bool pcie_ports_disabled; | ||
| 35 | |||
| 36 | /* | ||
| 37 | * If this switch is set, ACPI _OSC will be used to determine whether or not to | ||
| 38 | * enable PCIe port native services. | ||
| 39 | */ | ||
| 40 | bool pcie_ports_auto = true; | ||
| 41 | |||
| 42 | static int __init pcie_port_setup(char *str) | ||
| 43 | { | ||
| 44 | if (!strncmp(str, "compat", 6)) { | ||
| 45 | pcie_ports_disabled = true; | ||
| 46 | } else if (!strncmp(str, "native", 6)) { | ||
| 47 | pcie_ports_disabled = false; | ||
| 48 | pcie_ports_auto = false; | ||
| 49 | } else if (!strncmp(str, "auto", 4)) { | ||
| 50 | pcie_ports_disabled = false; | ||
| 51 | pcie_ports_auto = true; | ||
| 52 | } | ||
| 53 | |||
| 54 | return 1; | ||
| 55 | } | ||
| 56 | __setup("pcie_ports=", pcie_port_setup); | ||
| 57 | |||
| 32 | /* global data */ | 58 | /* global data */ |
| 33 | 59 | ||
| 34 | static int pcie_portdrv_restore_config(struct pci_dev *dev) | 60 | static int pcie_portdrv_restore_config(struct pci_dev *dev) |
| @@ -301,6 +327,11 @@ static int __init pcie_portdrv_init(void) | |||
| 301 | { | 327 | { |
| 302 | int retval; | 328 | int retval; |
| 303 | 329 | ||
| 330 | if (pcie_ports_disabled) { | ||
| 331 | pcie_no_aspm(); | ||
| 332 | return -EACCES; | ||
| 333 | } | ||
| 334 | |||
| 304 | dmi_check_system(pcie_portdrv_dmi_table); | 335 | dmi_check_system(pcie_portdrv_dmi_table); |
| 305 | 336 | ||
| 306 | retval = pcie_port_bus_register(); | 337 | retval = pcie_port_bus_register(); |
| @@ -315,11 +346,4 @@ static int __init pcie_portdrv_init(void) | |||
| 315 | return retval; | 346 | return retval; |
| 316 | } | 347 | } |
| 317 | 348 | ||
| 318 | static void __exit pcie_portdrv_exit(void) | ||
| 319 | { | ||
| 320 | pci_unregister_driver(&pcie_portdriver); | ||
| 321 | pcie_port_bus_unregister(); | ||
| 322 | } | ||
| 323 | |||
| 324 | module_init(pcie_portdrv_init); | 349 | module_init(pcie_portdrv_init); |
| 325 | module_exit(pcie_portdrv_exit); | ||
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 659eaa0fc48f..968cfea04f74 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c | |||
| @@ -49,7 +49,7 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf) | |||
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | /* these strings match up with the values in pci_bus_speed */ | 51 | /* these strings match up with the values in pci_bus_speed */ |
| 52 | static char *pci_bus_speed_strings[] = { | 52 | static const char *pci_bus_speed_strings[] = { |
| 53 | "33 MHz PCI", /* 0x00 */ | 53 | "33 MHz PCI", /* 0x00 */ |
| 54 | "66 MHz PCI", /* 0x01 */ | 54 | "66 MHz PCI", /* 0x01 */ |
| 55 | "66 MHz PCI-X", /* 0x02 */ | 55 | "66 MHz PCI-X", /* 0x02 */ |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index baacd98e7cc6..4de84ce3a927 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -377,9 +377,6 @@ struct acpi_pci_root { | |||
| 377 | 377 | ||
| 378 | u32 osc_support_set; /* _OSC state of support bits */ | 378 | u32 osc_support_set; /* _OSC state of support bits */ |
| 379 | u32 osc_control_set; /* _OSC state of control bits */ | 379 | u32 osc_control_set; /* _OSC state of control bits */ |
| 380 | u32 osc_control_qry; /* the latest _OSC query result */ | ||
| 381 | |||
| 382 | u32 osc_queried:1; /* has _OSC control been queried? */ | ||
| 383 | }; | 380 | }; |
| 384 | 381 | ||
| 385 | /* helper */ | 382 | /* helper */ |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index ccf94dc5acdf..c227757feb06 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
| @@ -304,8 +304,8 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context); | |||
| 304 | OSC_PCI_EXPRESS_PME_CONTROL | \ | 304 | OSC_PCI_EXPRESS_PME_CONTROL | \ |
| 305 | OSC_PCI_EXPRESS_AER_CONTROL | \ | 305 | OSC_PCI_EXPRESS_AER_CONTROL | \ |
| 306 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) | 306 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL) |
| 307 | 307 | extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, | |
| 308 | extern acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags); | 308 | u32 *mask, u32 req); |
| 309 | extern void acpi_early_init(void); | 309 | extern void acpi_early_init(void); |
| 310 | 310 | ||
| 311 | #else /* !CONFIG_ACPI */ | 311 | #else /* !CONFIG_ACPI */ |
diff --git a/include/linux/pci.h b/include/linux/pci.h index b1d17956a153..c8d95e369ff4 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
| @@ -1214,6 +1214,9 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus, | |||
| 1214 | unsigned int devfn) | 1214 | unsigned int devfn) |
| 1215 | { return NULL; } | 1215 | { return NULL; } |
| 1216 | 1216 | ||
| 1217 | static inline int pci_domain_nr(struct pci_bus *bus) | ||
| 1218 | { return 0; } | ||
| 1219 | |||
| 1217 | #define dev_is_pci(d) (false) | 1220 | #define dev_is_pci(d) (false) |
| 1218 | #define dev_is_pf(d) (false) | 1221 | #define dev_is_pf(d) (false) |
| 1219 | #define dev_num_vf(d) (0) | 1222 | #define dev_num_vf(d) (0) |
