]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 3 Jul 2023 06:07:10 +0000 (08:07 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 3 Jul 2023 06:07:10 +0000 (08:07 +0200)
added patches:
pci-acpi-call-_reg-when-transitioning-d-states.patch
pci-acpi-validate-acpi_pci_set_power_state-parameter.patch

queue-6.4/pci-acpi-call-_reg-when-transitioning-d-states.patch [new file with mode: 0644]
queue-6.4/pci-acpi-validate-acpi_pci_set_power_state-parameter.patch [new file with mode: 0644]
queue-6.4/series

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 (file)
index 0000000..822c1a1
--- /dev/null
@@ -0,0 +1,103 @@
+From 112a7f9c8edbf76f7cb83856a6cb6b60a210b659 Mon Sep 17 00:00:00 2001
+From: Mario Limonciello <mario.limonciello@amd.com>
+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 <mario.limonciello@amd.com>
+
+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 <mario.limonciello@amd.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Rafael J. Wysocki <rafael@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..5ffbb46
--- /dev/null
@@ -0,0 +1,77 @@
+From 5557b62634abbd55bab7b154ce4bca348ad7f96f Mon Sep 17 00:00:00 2001
+From: Bjorn Helgaas <bhelgaas@google.com>
+Date: Wed, 21 Jun 2023 16:36:12 -0500
+Subject: PCI/ACPI: Validate acpi_pci_set_power_state() parameter
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+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 <bhelgaas@google.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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)
index 1b26258b56670f003c840b074cab908ad88d6e7d..0e4b12c7bb184517b7469b2b6c107434a882f88a 100644 (file)
@@ -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