linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>,
	Mario Limonciello <mario.limonciello@amd.com>,
	Bjorn Helgaas <bhelgaas@google.com>,
	Sasha Levin <sashal@kernel.org>,
	rafael@kernel.org, robert.moore@intel.com,
	linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org,
	acpica-devel@lists.linuxfoundation.org
Subject: [PATCH AUTOSEL 6.1 03/60] PCI/ACPI: Account for _S0W of the target bridge in acpi_pci_bridge_d3()
Date: Fri,  3 Mar 2023 16:42:17 -0500	[thread overview]
Message-ID: <20230303214315.1447666-3-sashal@kernel.org> (raw)
In-Reply-To: <20230303214315.1447666-1-sashal@kernel.org>

From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>

[ Upstream commit 8133844a8f2434be9576850c6978179d7cca5c81 ]

It is questionable to allow a PCI bridge to go into D3 if it has _S0W
returning D2 or a shallower power state, so modify acpi_pci_bridge_d3(() to
always take the return value of _S0W for the target bridge into account.
That is, make it return 'false' if _S0W returns D2 or a shallower power
state for the target bridge regardless of its ancestor Root Port
properties.  Of course, this also causes 'false' to be returned if the Root
Port itself is the target and its _S0W returns D2 or a shallower power
state.

However, still allow bridges without _S0W that are power-manageable via
ACPI to enter D3 to retain the current code behavior in that case.

This fixes problems where a hotplug notification is missed because a bridge
is in D3.  That means hot-added devices such as USB4 docks (and the devices
they contain) and Thunderbolt 3 devices may not work.

Link: https://lore.kernel.org/linux-pci/20221031223356.32570-1-mario.limonciello@amd.com/
Link: https://lore.kernel.org/r/12155458.O9o76ZdvQC@kreacher
Reported-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/acpi/device_pm.c | 19 +++++++++++++++++
 drivers/pci/pci-acpi.c   | 45 +++++++++++++++++++++++++++-------------
 include/acpi/acpi_bus.h  |  1 +
 3 files changed, 51 insertions(+), 14 deletions(-)

diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 97450f4003cc9..f007116a84276 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -484,6 +484,25 @@ void acpi_dev_power_up_children_with_adr(struct acpi_device *adev)
 	acpi_dev_for_each_child(adev, acpi_power_up_if_adr_present, NULL);
 }
 
+/**
+ * acpi_dev_power_state_for_wake - Deepest power state for wakeup signaling
+ * @adev: ACPI companion of the target device.
+ *
+ * Evaluate _S0W for @adev and return the value produced by it or return
+ * ACPI_STATE_UNKNOWN on errors (including _S0W not present).
+ */
+u8 acpi_dev_power_state_for_wake(struct acpi_device *adev)
+{
+	unsigned long long state;
+	acpi_status status;
+
+	status = acpi_evaluate_integer(adev->handle, "_S0W", NULL, &state);
+	if (ACPI_FAILURE(status))
+		return ACPI_STATE_UNKNOWN;
+
+	return state;
+}
+
 #ifdef CONFIG_PM
 static DEFINE_MUTEX(acpi_pm_notifier_lock);
 static DEFINE_MUTEX(acpi_pm_notifier_install_lock);
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index a46fec776ad77..1698205dd73cb 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -976,24 +976,41 @@ bool acpi_pci_power_manageable(struct pci_dev *dev)
 bool acpi_pci_bridge_d3(struct pci_dev *dev)
 {
 	struct pci_dev *rpdev;
-	struct acpi_device *adev;
-	acpi_status status;
-	unsigned long long state;
+	struct acpi_device *adev, *rpadev;
 	const union acpi_object *obj;
 
 	if (acpi_pci_disabled || !dev->is_hotplug_bridge)
 		return false;
 
-	/* Assume D3 support if the bridge is power-manageable by ACPI. */
-	if (acpi_pci_power_manageable(dev))
-		return true;
+	adev = ACPI_COMPANION(&dev->dev);
+	if (adev) {
+		/*
+		 * If the bridge has _S0W, whether or not it can go into D3
+		 * depends on what is returned by that object.  In particular,
+		 * if the power state returned by _S0W is D2 or shallower,
+		 * entering D3 should not be allowed.
+		 */
+		if (acpi_dev_power_state_for_wake(adev) <= ACPI_STATE_D2)
+			return false;
+
+		/*
+		 * Otherwise, assume that the bridge can enter D3 so long as it
+		 * is power-manageable via ACPI.
+		 */
+		if (acpi_device_power_manageable(adev))
+			return true;
+	}
 
 	rpdev = pcie_find_root_port(dev);
 	if (!rpdev)
 		return false;
 
-	adev = ACPI_COMPANION(&rpdev->dev);
-	if (!adev)
+	if (rpdev == dev)
+		rpadev = adev;
+	else
+		rpadev = ACPI_COMPANION(&rpdev->dev);
+
+	if (!rpadev)
 		return false;
 
 	/*
@@ -1001,15 +1018,15 @@ bool acpi_pci_bridge_d3(struct pci_dev *dev)
 	 * doesn't supply a wakeup GPE via _PRW, it cannot signal hotplug
 	 * events from low-power states including D3hot and D3cold.
 	 */
-	if (!adev->wakeup.flags.valid)
+	if (!rpadev->wakeup.flags.valid)
 		return false;
 
 	/*
-	 * If the Root Port cannot wake itself from D3hot or D3cold, we
-	 * can't use D3.
+	 * In the bridge-below-a-Root-Port case, evaluate _S0W for the Root Port
+	 * to verify whether or not it can signal wakeup from D3.
 	 */
-	status = acpi_evaluate_integer(adev->handle, "_S0W", NULL, &state);
-	if (ACPI_SUCCESS(status) && state < ACPI_STATE_D3_HOT)
+	if (rpadev != adev &&
+	    acpi_dev_power_state_for_wake(rpadev) <= ACPI_STATE_D2)
 		return false;
 
 	/*
@@ -1018,7 +1035,7 @@ bool acpi_pci_bridge_d3(struct pci_dev *dev)
 	 * bridges *below* that Root Port can also signal hotplug events
 	 * while in D3.
 	 */
-	if (!acpi_dev_get_property(adev, "HotPlugSupportInD3",
+	if (!acpi_dev_get_property(rpadev, "HotPlugSupportInD3",
 				   ACPI_TYPE_INTEGER, &obj) &&
 	    obj->integer.value == 1)
 		return true;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index ab2d6266038a0..6badc50ec4e66 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -534,6 +534,7 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p);
 int acpi_device_update_power(struct acpi_device *device, int *state_p);
 bool acpi_bus_power_manageable(acpi_handle handle);
 void acpi_dev_power_up_children_with_adr(struct acpi_device *adev);
+u8 acpi_dev_power_state_for_wake(struct acpi_device *adev);
 int acpi_device_power_add_dependent(struct acpi_device *adev,
 				    struct device *dev);
 void acpi_device_power_remove_dependent(struct acpi_device *adev,
-- 
2.39.2


  parent reply	other threads:[~2023-03-03 21:44 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-03 21:42 [PATCH AUTOSEL 6.1 01/60] IB/hfi1: Update RMT size calculation Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 02/60] iommu/amd: Fix error handling for pdev_pri_ats_enable() Sasha Levin
2023-03-03 21:42 ` Sasha Levin [this message]
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 04/60] media: uvcvideo: Remove format descriptions Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 05/60] media: uvcvideo: Handle cameras with invalid descriptors Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 06/60] media: uvcvideo: Handle errors from calls to usb_string Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 07/60] media: uvcvideo: Quirk for autosuspend in Logitech B910 and C910 Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 08/60] media: uvcvideo: Silence memcpy() run-time false positive warnings Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 09/60] USB: fix memory leak with using debugfs_lookup() Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 10/60] cacheinfo: Fix shared_cpu_map to handle shared caches at different levels Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 11/60] staging: emxx_udc: Add checks for dma_alloc_coherent() Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 12/60] tty: fix out-of-bounds access in tty_driver_lookup_tty() Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 13/60] tty: serial: fsl_lpuart: disable the CTS when send break signal Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 14/60] serial: sc16is7xx: setup GPIO controller later in probe Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 15/60] mei: bus-fixup:upon error print return values of send and receive Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 16/60] parport_pc: Set up mode and ECR masks for Oxford Semiconductor devices Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 17/60] tools/iio/iio_utils:fix memory leak Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 18/60] bus: mhi: ep: Fix the debug message for MHI_PKT_TYPE_RESET_CHAN_CMD cmd Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 19/60] iio: accel: mma9551_core: Prevent uninitialized variable in mma9551_read_status_word() Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 20/60] iio: accel: mma9551_core: Prevent uninitialized variable in mma9551_read_config_word() Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 21/60] media: uvcvideo: Add GUID for BGRA/X 8:8:8:8 Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 22/60] firmware: coreboot: framebuffer: Ignore reserved pixel color bits Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 23/60] soundwire: bus_type: Avoid lockdep assert in sdw_drv_probe() Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 24/60] PCI: loongson: Prevent LS7A MRRS increases Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 25/60] staging: pi433: fix memory leak with using debugfs_lookup() Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 26/60] USB: dwc3: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 27/60] USB: chipidea: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 28/60] USB: ULPI: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 29/60] USB: uhci: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 30/60] USB: sl811: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 31/60] USB: fotg210: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 32/60] USB: isp116x: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 33/60] USB: isp1362: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 34/60] USB: gadget: gr_udc: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 35/60] USB: gadget: bcm63xx_udc: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 36/60] USB: gadget: lpc32xx_udc: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 37/60] USB: gadget: pxa25x_udc: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 38/60] USB: gadget: pxa27x_udc: " Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 39/60] usb: host: xhci: mvebu: Iterate over array indexes instead of using pointer math Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 40/60] USB: ene_usb6250: Allocate enough memory for full object Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 41/60] usb: uvc: Enumerate valid values for color matching Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 42/60] usb: gadget: uvc: Make bSourceID read/write Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 43/60] PCI: Align extra resources for hotplug bridges properly Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 44/60] PCI: Take other bus devices into account when distributing resources Sasha Levin
2023-03-03 21:42 ` [PATCH AUTOSEL 6.1 45/60] PCI: Distribute available resources for root buses, too Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 46/60] tty: pcn_uart: fix memory leak with using debugfs_lookup() Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 47/60] misc: vmw_balloon: " Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 48/60] drivers: base: component: " Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 49/60] drivers: base: dd: " Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 50/60] kernel/time/test_udelay.c: " Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 51/60] kernel/power/energy_model.c: " Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 52/60] kernel/fail_function: " Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 53/60] PCI: loongson: Add more devices that need MRRS quirk Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 54/60] PCI: Add ACS quirk for Wangxun NICs Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 55/60] PCI: pciehp: Add Qualcomm quirk for Command Completed erratum Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 56/60] phy: rockchip-typec: Fix unsigned comparison with less than zero Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 57/60] RDMA/cma: Distinguish between sockaddr_in and sockaddr_in6 by size Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 58/60] iommu: Attach device group to old domain in error path Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 59/60] soundwire: cadence: Remove wasted space in response_buf Sasha Levin
2023-03-03 21:43 ` [PATCH AUTOSEL 6.1 60/60] soundwire: cadence: Drain the RX FIFO after an IO timeout Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230303214315.1447666-3-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=acpica-devel@lists.linuxfoundation.org \
    --cc=bhelgaas@google.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=mario.limonciello@amd.com \
    --cc=rafael.j.wysocki@intel.com \
    --cc=rafael@kernel.org \
    --cc=robert.moore@intel.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).