From 1ce4ceee7f3ca1628bc31e83b667728c538c2fb7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 3 Jul 2023 08:07:10 +0200 Subject: [PATCH] 6.4-stable patches added patches: pci-acpi-call-_reg-when-transitioning-d-states.patch pci-acpi-validate-acpi_pci_set_power_state-parameter.patch --- ...all-_reg-when-transitioning-d-states.patch | 103 ++++++++++++++++++ ...e-acpi_pci_set_power_state-parameter.patch | 77 +++++++++++++ queue-6.4/series | 2 + 3 files changed, 182 insertions(+) create mode 100644 queue-6.4/pci-acpi-call-_reg-when-transitioning-d-states.patch create mode 100644 queue-6.4/pci-acpi-validate-acpi_pci_set_power_state-parameter.patch diff --git a/queue-6.4/pci-acpi-call-_reg-when-transitioning-d-states.patch b/queue-6.4/pci-acpi-call-_reg-when-transitioning-d-states.patch new file mode 100644 index 00000000000..822c1a1653f --- /dev/null +++ b/queue-6.4/pci-acpi-call-_reg-when-transitioning-d-states.patch @@ -0,0 +1,103 @@ +From 112a7f9c8edbf76f7cb83856a6cb6b60a210b659 Mon Sep 17 00:00:00 2001 +From: Mario Limonciello +Date: Tue, 20 Jun 2023 09:04:51 -0500 +Subject: PCI/ACPI: Call _REG when transitioning D-states +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mario Limonciello + +commit 112a7f9c8edbf76f7cb83856a6cb6b60a210b659 upstream. + +ACPI r6.5, sec 6.5.4, describes how AML is unable to access an +OperationRegion unless _REG has been called to connect a handler: + + The OS runs _REG control methods to inform AML code of a change in the + availability of an operation region. When an operation region handler is + unavailable, AML cannot access data fields in that region. (Operation + region writes will be ignored and reads will return indeterminate data.) + +The PCI core does not call _REG at any time, leading to the undefined +behavior mentioned in the spec. + +The spec explains that _REG should be executed to indicate whether a +given region can be accessed: + + Once _REG has been executed for a particular operation region, indicating + that the operation region handler is ready, a control method can access + fields in the operation region. Conversely, control methods must not + access fields in operation regions when _REG method execution has not + indicated that the operation region handler is ready. + +An example included in the spec demonstrates calling _REG when devices are +turned off: "when the host controller or bridge controller is turned off +or disabled, PCI Config Space Operation Regions for child devices are +no longer available. As such, ETH0’s _REG method will be run when it +is turned off and will again be run when PCI1 is turned off." + +It is reported that ASMedia PCIe GPIO controllers fail functional tests +after the system has returning from suspend (S3 or s2idle). This is because +the BIOS checks whether the OSPM has called the _REG method to determine +whether it can interact with the OperationRegion assigned to the device as +part of the other AML called for the device. + +To fix this issue, call acpi_evaluate_reg() when devices are transitioning +to D3cold or D0. + +[bhelgaas: split pci_power_t checking to preliminary patch] +Link: https://uefi.org/specs/ACPI/6.5/06_Device_Configuration.html#reg-region +Link: https://lore.kernel.org/r/20230620140451.21007-1-mario.limonciello@amd.com +Signed-off-by: Mario Limonciello +Signed-off-by: Bjorn Helgaas +Reviewed-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/pci-acpi.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/drivers/pci/pci-acpi.c ++++ b/drivers/pci/pci-acpi.c +@@ -1043,6 +1043,16 @@ bool acpi_pci_bridge_d3(struct pci_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_ + 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_ + 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; + } + diff --git a/queue-6.4/pci-acpi-validate-acpi_pci_set_power_state-parameter.patch b/queue-6.4/pci-acpi-validate-acpi_pci_set_power_state-parameter.patch new file mode 100644 index 00000000000..5ffbb46b3e6 --- /dev/null +++ b/queue-6.4/pci-acpi-validate-acpi_pci_set_power_state-parameter.patch @@ -0,0 +1,77 @@ +From 5557b62634abbd55bab7b154ce4bca348ad7f96f Mon Sep 17 00:00:00 2001 +From: Bjorn Helgaas +Date: Wed, 21 Jun 2023 16:36:12 -0500 +Subject: PCI/ACPI: Validate acpi_pci_set_power_state() parameter + +From: Bjorn Helgaas + +commit 5557b62634abbd55bab7b154ce4bca348ad7f96f upstream. + +Previously acpi_pci_set_power_state() assumed the requested power state was +valid (PCI_D0 ... PCI_D3cold). If a caller supplied something else, we +could index outside the state_conv[] array and pass junk to +acpi_device_set_power(). + +Validate the pci_power_t parameter and return -EINVAL if it's invalid. + +Link: https://lore.kernel.org/r/20230621222857.GA122930@bhelgaas +Signed-off-by: Bjorn Helgaas +Reviewed-by: Mario Limonciello +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/pci-acpi.c | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +--- a/drivers/pci/pci-acpi.c ++++ b/drivers/pci/pci-acpi.c +@@ -1053,32 +1053,37 @@ int acpi_pci_set_power_state(struct pci_ + [PCI_D3hot] = ACPI_STATE_D3_HOT, + [PCI_D3cold] = ACPI_STATE_D3_COLD, + }; +- int error = -EINVAL; ++ int error; + + /* If the ACPI device has _EJ0, ignore the device */ + if (!adev || acpi_has_method(adev->handle, "_EJ0")) + return -ENODEV; + + switch (state) { +- case PCI_D3cold: +- if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) == +- PM_QOS_FLAGS_ALL) { +- error = -EBUSY; +- break; +- } +- fallthrough; + case PCI_D0: + case PCI_D1: + case PCI_D2: + case PCI_D3hot: +- error = acpi_device_set_power(adev, state_conv[state]); ++ case PCI_D3cold: ++ break; ++ default: ++ return -EINVAL; + } + +- if (!error) +- pci_dbg(dev, "power state changed by ACPI to %s\n", +- acpi_power_state_string(adev->power.state)); ++ if (state == PCI_D3cold) { ++ if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) == ++ PM_QOS_FLAGS_ALL) ++ return -EBUSY; ++ } ++ ++ error = acpi_device_set_power(adev, state_conv[state]); ++ if (error) ++ return error; ++ ++ pci_dbg(dev, "power state changed by ACPI to %s\n", ++ acpi_power_state_string(adev->power.state)); + +- return error; ++ return 0; + } + + pci_power_t acpi_pci_get_power_state(struct pci_dev *dev) diff --git a/queue-6.4/series b/queue-6.4/series index 1b26258b566..0e4b12c7bb1 100644 --- a/queue-6.4/series +++ b/queue-6.4/series @@ -1,2 +1,4 @@ xtensa-fix-lock_mm_and_find_vma-in-case-vma-not-found.patch tools-nolibc-x86_64-disable-stack-protector-for-_start.patch +pci-acpi-validate-acpi_pci_set_power_state-parameter.patch +pci-acpi-call-_reg-when-transitioning-d-states.patch -- 2.47.3