Skip to content

Commit 28eb5f2

Browse files
rjwysockijbarnes993
authored andcommitted
PCI: PCIe: Ask BIOS for control of all native services at once
After commit 852972a (ACPI: Disable ASPM if the platform won't provide _OSC control for PCIe) control of the PCIe Capability Structure is unconditionally requested by acpi_pci_root_add(), which in principle may cause problems to happen in two ways. First, the BIOS may refuse to give control of the PCIe Capability Structure if it is not asked for any of the _OSC features depending on it at the same time. Second, the BIOS may assume that control of the _OSC features depending on the PCIe Capability Structure will be requested in the future and may behave incorrectly if that doesn't happen. For this reason, control of the PCIe Capability Structure should always be requested along with control of any other _OSC features that may depend on it (ie. PCIe native PME, PCIe native hot-plug, PCIe AER). Rework the PCIe port driver so that (1) it checks which native PCIe port services can be enabled, according to the BIOS, and (2) it requests control of all these services simultaneously. In particular, this causes pcie_portdrv_probe() to fail if the BIOS refuses to grant control of the PCIe Capability Structure, which means that no native PCIe port services can be enabled for the PCIe Root Complex the given port belongs to. If that happens, ASPM is disabled to avoid problems with mishandling it by the part of the PCIe hierarchy for which control of the PCIe Capability Structure has not been received. Make it possible to override this behavior using 'pcie_ports=native' (use the PCIe native services regardless of the BIOS response to the control request), or 'pcie_ports=compat' (do not use the PCIe native services at all). Accordingly, rework the existing PCIe port service drivers so that they don't request control of the services directly. Signed-off-by: Rafael J. Wysocki <[email protected]> Signed-off-by: Jesse Barnes <[email protected]>
1 parent 75fb60f commit 28eb5f2

File tree

17 files changed

+155
-237
lines changed

17 files changed

+155
-237
lines changed

Documentation/kernel-parameters.txt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2043,18 +2043,17 @@ and is between 256 and 4096 characters. It is defined in the file
20432043
WARNING: Forcing ASPM on may cause system lockups.
20442044

20452045
pcie_ports= [PCIE] PCIe ports handling:
2046+
auto Ask the BIOS whether or not to use native PCIe services
2047+
associated with PCIe ports (PME, hot-plug, AER). Use
2048+
them only if that is allowed by the BIOS.
2049+
native Use native PCIe services associated with PCIe ports
2050+
unconditionally.
20462051
compat Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe
20472052
ports driver.
20482053

20492054
pcie_pme= [PCIE,PM] Native PCIe PME signaling options:
2050-
Format: {auto|force}[,nomsi]
2051-
auto Use native PCIe PME signaling if the BIOS allows the
2052-
kernel to control PCIe config registers of root ports.
2053-
force Use native PCIe PME signaling even if the BIOS refuses
2054-
to allow the kernel to control the relevant PCIe config
2055-
registers.
20562055
nomsi Do not use MSI for native PCIe PME signaling (this makes
2057-
all PCIe root ports use INTx for everything).
2056+
all PCIe root ports use INTx for all services).
20582057

20592058
pcmv= [HW,PCMCIA] BadgePAD 4
20602059

drivers/acpi/pci_root.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include <linux/pm_runtime.h>
3434
#include <linux/pci.h>
3535
#include <linux/pci-acpi.h>
36-
#include <linux/pci-aspm.h>
3736
#include <linux/acpi.h>
3837
#include <linux/slab.h>
3938
#include <acpi/acpi_bus.h>
@@ -568,14 +567,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
568567
if (flags != base_flags)
569568
acpi_pci_osc_support(root, flags);
570569

571-
flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL;
572-
status = acpi_pci_osc_control_set(root->device->handle, &flags, flags);
573-
574-
if (ACPI_FAILURE(status)) {
575-
printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n");
576-
pcie_no_aspm();
577-
}
578-
579570
pci_acpi_add_bus_pm_notifier(device, root->bus);
580571
if (device->wakeup.flags.run_wake)
581572
device_set_run_wake(root->bus->bridge, true);

drivers/pci/hotplug/acpi_pcihp.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
338338
acpi_handle chandle, handle;
339339
struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
340340

341-
flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
342-
OSC_SHPC_NATIVE_HP_CONTROL |
343-
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
341+
flags &= OSC_SHPC_NATIVE_HP_CONTROL;
344342
if (!flags) {
345343
err("Invalid flags %u specified!\n", flags);
346344
return -EINVAL;

drivers/pci/hotplug/pciehp.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -176,19 +176,7 @@ static inline void pciehp_firmware_init(void)
176176
{
177177
pciehp_acpi_slot_detection_init();
178178
}
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-
}
190179
#else
191180
#define pciehp_firmware_init() do {} while (0)
192-
#define pciehp_get_hp_hw_control_from_firmware(dev) 0
193181
#endif /* CONFIG_ACPI */
194182
#endif /* _PCIEHP_H */

drivers/pci/hotplug/pciehp_acpi.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,7 @@ static int __init dummy_probe(struct pcie_device *dev)
8585
acpi_handle handle;
8686
struct dummy_slot *slot, *tmp;
8787
struct pci_dev *pdev = dev->port;
88-
/* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
89-
if (pciehp_get_hp_hw_control_from_firmware(pdev))
90-
return -ENODEV;
88+
9189
pos = pci_pcie_cap(pdev);
9290
if (!pos)
9391
return -ENODEV;

drivers/pci/hotplug/pciehp_core.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ module_param(pciehp_force, bool, 0644);
5959
MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
6060
MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
6161
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");
6363

6464
#define PCIE_MODULE_NAME "pciehp"
6565

@@ -235,7 +235,7 @@ static int pciehp_probe(struct pcie_device *dev)
235235
dev_info(&dev->device,
236236
"Bypassing BIOS check for pciehp use on %s\n",
237237
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))
239239
goto err_out_none;
240240

241241
ctrl = pcie_init(dev);

drivers/pci/pcie/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
obj-$(CONFIG_PCIEASPM) += aspm.o
77

88
pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o
9+
pcieportdrv-$(CONFIG_ACPI) += portdrv_acpi.o
910

1011
obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
1112

drivers/pci/pcie/aer/aerdrv_acpi.c

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,42 +19,6 @@
1919
#include <acpi/apei.h>
2020
#include "aerdrv.h"
2121

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-
u32 flags = OSC_PCI_EXPRESS_AER_CONTROL |
43-
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL;
44-
status = acpi_pci_osc_control_set(handle, &flags, flags);
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-
5822
#ifdef CONFIG_ACPI_APEI
5923
static inline int hest_match_pci(struct acpi_hest_aer_common *p,
6024
struct pci_dev *pci)

drivers/pci/pcie/aer/aerdrv_core.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -772,22 +772,10 @@ void aer_isr(struct work_struct *work)
772772
*/
773773
int aer_init(struct pcie_device *dev)
774774
{
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:
786775
if (forceload) {
787776
dev_printk(KERN_DEBUG, &dev->device,
788777
"aerdrv forceload requested.\n");
789778
pcie_aer_force_firmware_first(dev->port, 0);
790-
return 0;
791779
}
792-
return -ENXIO;
780+
return 0;
793781
}

drivers/pci/pcie/pme/Makefile

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,4 @@
22
# Makefile for PCI-Express Root Port PME signaling driver
33
#
44

5-
obj-$(CONFIG_PCIE_PME) += pmedriver.o
6-
7-
pmedriver-objs := pcie_pme.o
8-
pmedriver-$(CONFIG_ACPI) += pcie_pme_acpi.o
5+
obj-$(CONFIG_PCIE_PME) += pcie_pme.o

0 commit comments

Comments
 (0)