Commit 7e229f0e authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/pm'

- Reduce wait time for secondary bus to be ready to speed up resume (Mika
  Westerberg)

- Avoid putting EloPOS E2/S2/H2 (as well as Elo i2) PCIe Ports in D3cold
  (Ondrej Zary)

- Call _REG when transitioning D-states so AML that uses the PCI config
  space OpRegion works, which fixes some ASMedia GPIO controllers (Mario
  Limonciello)

* pci/pm:
  PCI/ACPI: Call _REG when transitioning D-states
  PCI/ACPI: Validate acpi_pci_set_power_state() parameter
  PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
  PCI/PM: Shorten pci_bridge_wait_for_secondary_bus() wait time for slow links
parents db5ccb2e 112a7f9c
Loading
Loading
Loading
Loading
+40 −13
Original line number Diff line number Diff line
@@ -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);
@@ -1053,32 +1063,49 @@ int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
		[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)
	if (state == PCI_D3cold) {
		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]);
	if (error)
		return error;

	pci_dbg(dev, "power state changed by ACPI to %s\n",
	        acpi_power_state_string(adev->power.state));

	return error;
	/*
	 * 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;
}

pci_power_t acpi_pci_get_power_state(struct pci_dev *dev)
+42 −17
Original line number Diff line number Diff line
@@ -64,6 +64,13 @@ struct pci_pme_device {

#define PME_TIMEOUT 1000 /* How long between PME checks */

/*
 * Following exit from Conventional Reset, devices must be ready within 1 sec
 * (PCIe r6.0 sec 6.6.1).  A D3cold to D0 transition implies a Conventional
 * Reset (PCIe r6.0 sec 5.8).
 */
#define PCI_RESET_WAIT 1000 /* msec */

/*
 * Devices may extend the 1 sec period through Request Retry Status
 * completions (PCIe r6.0 sec 2.3.1).  The spec does not provide an upper
@@ -2968,13 +2975,13 @@ static const struct dmi_system_id bridge_d3_blacklist[] = {
	{
		/*
		 * Downstream device is not accessible after putting a root port
		 * into D3cold and back into D0 on Elo i2.
		 * into D3cold and back into D0 on Elo Continental Z2 board
		 */
		.ident = "Elo i2",
		.ident = "Elo Continental Z2",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Elo Touch Solutions"),
			DMI_MATCH(DMI_PRODUCT_NAME, "Elo i2"),
			DMI_MATCH(DMI_PRODUCT_VERSION, "RevB"),
			DMI_MATCH(DMI_BOARD_VENDOR, "Elo Touch Solutions"),
			DMI_MATCH(DMI_BOARD_NAME, "Geminilake"),
			DMI_MATCH(DMI_BOARD_VERSION, "Continental Z2"),
		},
	},
#endif
@@ -5102,11 +5109,9 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
	 *
	 * However, 100 ms is the minimum and the PCIe spec says the
	 * software must allow at least 1s before it can determine that the
	 * device that did not respond is a broken device. There is
	 * evidence that 100 ms is not always enough, for example certain
	 * Titan Ridge xHCI controller does not always respond to
	 * configuration requests if we only wait for 100 ms (see
	 * https://bugzilla.kernel.org/show_bug.cgi?id=203885).
	 * device that did not respond is a broken device. Also device can
	 * take longer than that to respond if it indicates so through Request
	 * Retry Status completions.
	 *
	 * Therefore we wait for 100 ms and check for the device presence
	 * until the timeout expires.
@@ -5115,9 +5120,30 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
		return 0;

	if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) {
		u16 status;

		pci_dbg(dev, "waiting %d ms for downstream link\n", delay);
		msleep(delay);
	} else {

		if (!pci_dev_wait(child, reset_type, PCI_RESET_WAIT - delay))
			return 0;

		/*
		 * If the port supports active link reporting we now check
		 * whether the link is active and if not bail out early with
		 * the assumption that the device is not present anymore.
		 */
		if (!dev->link_active_reporting)
			return -ENOTTY;

		pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &status);
		if (!(status & PCI_EXP_LNKSTA_DLLLA))
			return -ENOTTY;

		return pci_dev_wait(child, reset_type,
				    PCIE_RESET_READY_POLL_MS - PCI_RESET_WAIT);
	}

	pci_dbg(dev, "waiting %d ms for downstream link, after activation\n",
		delay);
	if (!pcie_wait_for_link_delay(dev, true, delay)) {
@@ -5125,7 +5151,6 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
		pci_info(dev, "Data Link Layer Link Active not set in 1000 msec\n");
		return -ENOTTY;
	}
	}

	return pci_dev_wait(child, reset_type,
			    PCIE_RESET_READY_POLL_MS - delay);
+0 −7
Original line number Diff line number Diff line
@@ -66,13 +66,6 @@ struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev,
#define PCI_PM_D3HOT_WAIT       10	/* msec */
#define PCI_PM_D3COLD_WAIT      100	/* msec */

/*
 * Following exit from Conventional Reset, devices must be ready within 1 sec
 * (PCIe r6.0 sec 6.6.1).  A D3cold to D0 transition implies a Conventional
 * Reset (PCIe r6.0 sec 5.8).
 */
#define PCI_RESET_WAIT		1000	/* msec */

void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
void pci_refresh_power_state(struct pci_dev *dev);
int pci_power_up(struct pci_dev *dev);