Commit 35e7f73c authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'topic/huang-d3cold-v7' into next

* topic/huang-d3cold-v7:
  PCI/PM: add PCIe runtime D3cold support
  PCI: do not call pci_set_power_state with PCI_D3cold
  PCI/PM: add runtime PM support to PCIe port
  ACPI/PM: specify lowest allowed state for device sleep state
parents e5028b52 448bd857
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -264,7 +264,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_d3delay_fixup);

static void __devinit mrst_power_off_unused_dev(struct pci_dev *dev)
{
	pci_set_power_state(dev, PCI_D3cold);
	pci_set_power_state(dev, PCI_D3hot);
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0801, mrst_power_off_unused_dev);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0809, mrst_power_off_unused_dev);
+19 −5
Original line number Diff line number Diff line
@@ -716,8 +716,9 @@ int acpi_suspend(u32 acpi_state)
 *	@dev: device to examine; its driver model wakeup flags control
 *		whether it should be able to wake up the system
 *	@d_min_p: used to store the upper limit of allowed states range
 *	Return value: preferred power state of the device on success, -ENODEV on
 *		failure (ie. if there's no 'struct acpi_device' for @dev)
 *	@d_max_in: specify the lowest allowed states
 *	Return value: preferred power state of the device on success, -ENODEV
 *	(ie. if there's no 'struct acpi_device' for @dev) or -EINVAL on failure
 *
 *	Find the lowest power (highest number) ACPI device power state that
 *	device @dev can be in while the system is in the sleep state represented
@@ -732,13 +733,15 @@ int acpi_suspend(u32 acpi_state)
 *	via @wake.
 */

int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
{
	acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
	struct acpi_device *adev;
	char acpi_method[] = "_SxD";
	unsigned long long d_min, d_max;

	if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3)
		return -EINVAL;
	if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
		printk(KERN_DEBUG "ACPI handle has no context!\n");
		return -ENODEV;
@@ -746,8 +749,10 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)

	acpi_method[2] = '0' + acpi_target_sleep_state;
	/*
	 * If the sleep state is S0, we will return D3, but if the device has
	 * _S0W, we will use the value from _S0W
	 * If the sleep state is S0, the lowest limit from ACPI is D3,
	 * but if the device has _S0W, we will use the value from _S0W
	 * as the lowest limit from ACPI.  Finally, we will constrain
	 * the lowest limit with the specified one.
	 */
	d_min = ACPI_STATE_D0;
	d_max = ACPI_STATE_D3;
@@ -791,8 +796,17 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
		}
	}

	if (d_max_in < d_min)
		return -EINVAL;
	if (d_min_p)
		*d_min_p = d_min;
	/* constrain d_max with specified lowest limit (max number) */
	if (d_max > d_max_in) {
		for (d_max = d_max_in; d_max > d_min; d_max--) {
			if (adev->power.states[d_max].flags.valid)
				break;
		}
	}
	return d_max;
}
#endif /* CONFIG_PM */
+1 −1
Original line number Diff line number Diff line
@@ -180,7 +180,7 @@ static int cb710_suspend(struct pci_dev *pdev, pm_message_t state)
	pci_save_state(pdev);
	pci_disable_device(pdev);
	if (state.event & PM_EVENT_SLEEP)
		pci_set_power_state(pdev, PCI_D3cold);
		pci_set_power_state(pdev, PCI_D3hot);
	return 0;
}

+19 −3
Original line number Diff line number Diff line
@@ -48,6 +48,12 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
	if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev)
		return;

	if (pci_dev->current_state == PCI_D3cold) {
		pci_wakeup_event(pci_dev);
		pm_runtime_resume(&pci_dev->dev);
		return;
	}

	if (!pci_dev->pm_cap || !pci_dev->pme_support
	     || pci_check_pme_status(pci_dev)) {
		if (pci_dev->pme_poll)
@@ -201,9 +207,13 @@ phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)

static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
{
	int acpi_state;
	int acpi_state, d_max;

	acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL);
	if (pdev->no_d3cold)
		d_max = ACPI_STATE_D3_HOT;
	else
		d_max = ACPI_STATE_D3_COLD;
	acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL, d_max);
	if (acpi_state < 0)
		return PCI_POWER_ERROR;

@@ -310,7 +320,13 @@ static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable)

static int acpi_pci_run_wake(struct pci_dev *dev, bool enable)
{
	if (dev->pme_interrupt)
	/*
	 * Per PCI Express Base Specification Revision 2.0 section
	 * 5.3.3.2 Link Wakeup, platform support is needed for D3cold
	 * waking up to power on the main link even if there is PME
	 * support for D3cold
	 */
	if (dev->pme_interrupt && !dev->runtime_d3cold)
		return 0;

	if (!acpi_pm_device_run_wake(&dev->dev, enable))
+9 −1
Original line number Diff line number Diff line
@@ -1019,10 +1019,13 @@ static int pci_pm_runtime_suspend(struct device *dev)
	if (!pm || !pm->runtime_suspend)
		return -ENOSYS;

	pci_dev->no_d3cold = false;
	error = pm->runtime_suspend(dev);
	suspend_report_result(pm->runtime_suspend, error);
	if (error)
		return error;
	if (!pci_dev->d3cold_allowed)
		pci_dev->no_d3cold = true;

	pci_fixup_device(pci_fixup_suspend, pci_dev);

@@ -1044,6 +1047,7 @@ static int pci_pm_runtime_suspend(struct device *dev)

static int pci_pm_runtime_resume(struct device *dev)
{
	int rc;
	struct pci_dev *pci_dev = to_pci_dev(dev);
	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;

@@ -1054,7 +1058,11 @@ static int pci_pm_runtime_resume(struct device *dev)
	__pci_enable_wake(pci_dev, PCI_D0, true, false);
	pci_fixup_device(pci_fixup_resume, pci_dev);

	return pm->runtime_resume(dev);
	rc = pm->runtime_resume(dev);

	pci_dev->runtime_d3cold = false;

	return rc;
}

static int pci_pm_runtime_idle(struct device *dev)
Loading