summaryrefslogtreecommitdiff
path: root/drivers/pci/pci-acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r--drivers/pci/pci-acpi.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index bf545f719182..a05350a4e49c 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -1043,6 +1043,16 @@ bool acpi_pci_bridge_d3(struct pci_dev *dev)
return false;
}
+static void acpi_pci_config_space_access(struct pci_dev *dev, bool enable)
+{
+ int val = enable ? ACPI_REG_CONNECT : ACPI_REG_DISCONNECT;
+ int ret = acpi_evaluate_reg(ACPI_HANDLE(&dev->dev),
+ ACPI_ADR_SPACE_PCI_CONFIG, val);
+ if (ret)
+ pci_dbg(dev, "ACPI _REG %s evaluation failed (%d)\n",
+ enable ? "connect" : "disconnect", ret);
+}
+
int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
{
struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
@@ -1074,6 +1084,9 @@ int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
PM_QOS_FLAGS_ALL)
return -EBUSY;
+
+ /* Notify AML lack of PCI config space availability */
+ acpi_pci_config_space_access(dev, false);
}
error = acpi_device_set_power(adev, state_conv[state]);
@@ -1083,6 +1096,15 @@ int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
pci_dbg(dev, "power state changed by ACPI to %s\n",
acpi_power_state_string(adev->power.state));
+ /*
+ * Notify AML of PCI config space availability. Config space is
+ * accessible in all states except D3cold; the only transitions
+ * that change availability are transitions to D3cold and from
+ * D3cold to D0.
+ */
+ if (state == PCI_D0)
+ acpi_pci_config_space_access(dev, true);
+
return 0;
}