diff mbox series

[v3,06/17] PCI: Fix us->ms conversion in pci_acpi_optimize_delay

Message ID 20200303132852.13184-7-stanspas@amazon.com
State New
Headers show
Series Improve PCI device post-reset readiness polling | expand

Commit Message

Stanislav Spassov March 3, 2020, 1:28 p.m. UTC
From: Stanislav Spassov <stanspas@amazon.de>

_DSM Function 9 returns device readiness durations in microseconds.

Without this fix, integer truncation could cause msleep()-ing for up to
999us less than actually requested by the firmware.

Specifically, if the firmware specifies a 500us delay, msleep(0) would
be invoked by the users of the delay values optimized here.

Signed-off-by: Stanislav Spassov <stanspas@amazon.de>
---
 drivers/pci/pci-acpi.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index a8fa13d6089d..b147b61c6668 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -1219,6 +1219,11 @@  static void pci_acpi_optimize_delay(struct pci_dev *pdev,
 				    acpi_handle handle)
 {
 	struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus);
+	/*
+	 * _DSM 9 provides values in microseconds, but the kernel uses msleep()
+	 * when waiting, so the code below rounds up when setting value in ms
+	 */
+	u64 value_us;
 	int value;
 	union acpi_object *obj, *elements;
 
@@ -1233,12 +1238,18 @@  static void pci_acpi_optimize_delay(struct pci_dev *pdev,
 	if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 5) {
 		elements = obj->package.elements;
 		if (elements[0].type == ACPI_TYPE_INTEGER) {
-			value = (int)elements[0].integer.value / 1000;
+			value_us = elements[0].integer.value;
+			value = (int)value_us / 1000;
+			if ((int)value_us % 1000 > 0)
+				value++;
 			if (value < PCI_PM_D3COLD_WAIT)
 				pdev->d3cold_delay = value;
 		}
 		if (elements[3].type == ACPI_TYPE_INTEGER) {
-			value = (int)elements[3].integer.value / 1000;
+			value_us = elements[3].integer.value;
+			value = (int)value_us / 1000;
+			if ((int)value_us % 1000 > 0)
+				value++;
 			if (value < PCI_PM_D3_WAIT)
 				pdev->d3_delay = value;
 		}