Commit af8bb9f8 authored by Bjorn Helgaas's avatar Bjorn Helgaas

PCI/ACPI: Request LTR control from platform before using it

Per the PCI Firmware spec r3.2, sec 4.5, an ACPI-based OS should use _OSC
to request control of Latency Tolerance Reporting (LTR) before using it.

Request control of LTR, and if the platform does not grant control, don't
use it.

N.B. If the hardware supports LTR and the ASPM L1.2 substate but the BIOS
doesn't support LTR in _OSC, we previously would enable ASPM L1.2.  This
patch will prevent us from enabling ASPM L1.2 in that case.  It does not
prevent us from enabling PCI-PM L1.2, since that doesn't depend on LTR.
See PCIe r40, sec 5.5.1, for the L1 PM substate entry conditions.
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Reviewed-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 9ab105de
...@@ -153,6 +153,7 @@ static struct pci_osc_bit_struct pci_osc_control_bit[] = { ...@@ -153,6 +153,7 @@ static struct pci_osc_bit_struct pci_osc_control_bit[] = {
{ OSC_PCI_EXPRESS_PME_CONTROL, "PME" }, { OSC_PCI_EXPRESS_PME_CONTROL, "PME" },
{ OSC_PCI_EXPRESS_AER_CONTROL, "AER" }, { OSC_PCI_EXPRESS_AER_CONTROL, "AER" },
{ OSC_PCI_EXPRESS_CAPABILITY_CONTROL, "PCIeCapability" }, { OSC_PCI_EXPRESS_CAPABILITY_CONTROL, "PCIeCapability" },
{ OSC_PCI_EXPRESS_LTR_CONTROL, "LTR" },
}; };
static void decode_osc_bits(struct acpi_pci_root *root, char *msg, u32 word, static void decode_osc_bits(struct acpi_pci_root *root, char *msg, u32 word,
...@@ -475,6 +476,9 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm) ...@@ -475,6 +476,9 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm)
| OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL
| OSC_PCI_EXPRESS_PME_CONTROL; | OSC_PCI_EXPRESS_PME_CONTROL;
if (IS_ENABLED(CONFIG_PCIEASPM))
control |= OSC_PCI_EXPRESS_LTR_CONTROL;
if (pci_aer_available()) { if (pci_aer_available()) {
if (aer_acpi_firmware_first()) if (aer_acpi_firmware_first())
dev_info(&device->dev, dev_info(&device->dev,
...@@ -905,6 +909,8 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root, ...@@ -905,6 +909,8 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root,
host_bridge->native_aer = 0; host_bridge->native_aer = 0;
if (!(root->osc_control_set & OSC_PCI_EXPRESS_PME_CONTROL)) if (!(root->osc_control_set & OSC_PCI_EXPRESS_PME_CONTROL))
host_bridge->native_pme = 0; host_bridge->native_pme = 0;
if (!(root->osc_control_set & OSC_PCI_EXPRESS_LTR_CONTROL))
host_bridge->native_ltr = 0;
pci_scan_child_bus(bus); pci_scan_child_bus(bus);
pci_set_host_bridge_release(host_bridge, acpi_pci_root_release_info, pci_set_host_bridge_release(host_bridge, acpi_pci_root_release_info,
......
...@@ -554,6 +554,7 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv) ...@@ -554,6 +554,7 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
bridge->native_aer = 1; bridge->native_aer = 1;
bridge->native_hotplug = 1; bridge->native_hotplug = 1;
bridge->native_pme = 1; bridge->native_pme = 1;
bridge->native_ltr = 1;
return bridge; return bridge;
} }
...@@ -1954,9 +1955,13 @@ static void pci_configure_relaxed_ordering(struct pci_dev *dev) ...@@ -1954,9 +1955,13 @@ static void pci_configure_relaxed_ordering(struct pci_dev *dev)
static void pci_configure_ltr(struct pci_dev *dev) static void pci_configure_ltr(struct pci_dev *dev)
{ {
#ifdef CONFIG_PCIEASPM #ifdef CONFIG_PCIEASPM
struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
u32 cap; u32 cap;
struct pci_dev *bridge; struct pci_dev *bridge;
if (!host->native_ltr)
return;
if (!pci_is_pcie(dev)) if (!pci_is_pcie(dev))
return; return;
......
...@@ -506,7 +506,8 @@ extern bool osc_pc_lpi_support_confirmed; ...@@ -506,7 +506,8 @@ extern bool osc_pc_lpi_support_confirmed;
#define OSC_PCI_EXPRESS_PME_CONTROL 0x00000004 #define OSC_PCI_EXPRESS_PME_CONTROL 0x00000004
#define OSC_PCI_EXPRESS_AER_CONTROL 0x00000008 #define OSC_PCI_EXPRESS_AER_CONTROL 0x00000008
#define OSC_PCI_EXPRESS_CAPABILITY_CONTROL 0x00000010 #define OSC_PCI_EXPRESS_CAPABILITY_CONTROL 0x00000010
#define OSC_PCI_CONTROL_MASKS 0x0000001f #define OSC_PCI_EXPRESS_LTR_CONTROL 0x00000020
#define OSC_PCI_CONTROL_MASKS 0x0000003f
#define ACPI_GSB_ACCESS_ATTRIB_QUICK 0x00000002 #define ACPI_GSB_ACCESS_ATTRIB_QUICK 0x00000002
#define ACPI_GSB_ACCESS_ATTRIB_SEND_RCV 0x00000004 #define ACPI_GSB_ACCESS_ATTRIB_SEND_RCV 0x00000004
......
...@@ -473,6 +473,7 @@ struct pci_host_bridge { ...@@ -473,6 +473,7 @@ struct pci_host_bridge {
unsigned int native_aer:1; /* OS may use PCIe AER */ unsigned int native_aer:1; /* OS may use PCIe AER */
unsigned int native_hotplug:1; /* OS may use PCIe hotplug */ unsigned int native_hotplug:1; /* OS may use PCIe hotplug */
unsigned int native_pme:1; /* OS may use PCIe PME */ unsigned int native_pme:1; /* OS may use PCIe PME */
unsigned int native_ltr:1; /* OS may use PCIe LTR */
/* Resource alignment requirements */ /* Resource alignment requirements */
resource_size_t (*align_resource)(struct pci_dev *dev, resource_size_t (*align_resource)(struct pci_dev *dev,
const struct resource *res, const struct resource *res,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment