Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 90dc8b65 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull power management fixes from Rafael Wysocki:
 "These fix a PCI power management regression introduced during the 4.17
  cycle and fix up the recently added support for devices in multiple
  power domains.

  Specifics:

   - Resume parallel PCI (non-PCIe) bridges on suspend-to-RAM (ACP S3)
     to avoid confusing the platform firmware which started to happen
     after a core power management regression fix that went in during
     the 4.17 cycle (Rafael Wysocki).

   - Fix up the recently added support for devices in multiple power
     domains by avoiding to power up the entire domain unnecessarily
     when attaching a device to it (Ulf Hansson)"

* tag 'pm-4.18-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  PM / Domains: Don't power on at attach for the multi PM domain case
  PCI / ACPI / PM: Resume bridges w/o drivers on suspend-to-RAM
parents b19b9282 88b96088
Loading
Loading
Loading
Loading
+9 −7
Original line number Original line Diff line number Diff line
@@ -2235,7 +2235,7 @@ static void genpd_dev_pm_sync(struct device *dev)
}
}


static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
				 unsigned int index)
				 unsigned int index, bool power_on)
{
{
	struct of_phandle_args pd_args;
	struct of_phandle_args pd_args;
	struct generic_pm_domain *pd;
	struct generic_pm_domain *pd;
@@ -2271,9 +2271,11 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
	dev->pm_domain->detach = genpd_dev_pm_detach;
	dev->pm_domain->detach = genpd_dev_pm_detach;
	dev->pm_domain->sync = genpd_dev_pm_sync;
	dev->pm_domain->sync = genpd_dev_pm_sync;


	if (power_on) {
		genpd_lock(pd);
		genpd_lock(pd);
		ret = genpd_power_on(pd, 0);
		ret = genpd_power_on(pd, 0);
		genpd_unlock(pd);
		genpd_unlock(pd);
	}


	if (ret)
	if (ret)
		genpd_remove_device(pd, dev);
		genpd_remove_device(pd, dev);
@@ -2307,7 +2309,7 @@ int genpd_dev_pm_attach(struct device *dev)
				       "#power-domain-cells") != 1)
				       "#power-domain-cells") != 1)
		return 0;
		return 0;


	return __genpd_dev_pm_attach(dev, dev->of_node, 0);
	return __genpd_dev_pm_attach(dev, dev->of_node, 0, true);
}
}
EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);


@@ -2359,14 +2361,14 @@ struct device *genpd_dev_pm_attach_by_id(struct device *dev,
	}
	}


	/* Try to attach the device to the PM domain at the specified index. */
	/* Try to attach the device to the PM domain at the specified index. */
	ret = __genpd_dev_pm_attach(genpd_dev, dev->of_node, index);
	ret = __genpd_dev_pm_attach(genpd_dev, dev->of_node, index, false);
	if (ret < 1) {
	if (ret < 1) {
		device_unregister(genpd_dev);
		device_unregister(genpd_dev);
		return ret ? ERR_PTR(ret) : NULL;
		return ret ? ERR_PTR(ret) : NULL;
	}
	}


	pm_runtime_set_active(genpd_dev);
	pm_runtime_enable(genpd_dev);
	pm_runtime_enable(genpd_dev);
	genpd_queue_power_off_work(dev_to_genpd(genpd_dev));


	return genpd_dev;
	return genpd_dev;
}
}
+12 −0
Original line number Original line Diff line number Diff line
@@ -629,6 +629,18 @@ static bool acpi_pci_need_resume(struct pci_dev *dev)
{
{
	struct acpi_device *adev = ACPI_COMPANION(&dev->dev);
	struct acpi_device *adev = ACPI_COMPANION(&dev->dev);


	/*
	 * In some cases (eg. Samsung 305V4A) leaving a bridge in suspend over
	 * system-wide suspend/resume confuses the platform firmware, so avoid
	 * doing that, unless the bridge has a driver that should take care of
	 * the PM handling.  According to Section 16.1.6 of ACPI 6.2, endpoint
	 * devices are expected to be in D3 before invoking the S3 entry path
	 * from the firmware, so they should not be affected by this issue.
	 */
	if (pci_is_bridge(dev) && !dev->driver &&
	    acpi_target_system_state() != ACPI_STATE_S0)
		return true;

	if (!adev || !acpi_device_power_manageable(adev))
	if (!adev || !acpi_device_power_manageable(adev))
		return false;
		return false;