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

Commit 92266e1d authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branches 'pm-pci' and 'pm-core'

* pm-pci:
  PCI / PM: Fix small typo in documentation
  PCI / PM: constify pci_platform_pm_ops structure

* pm-core:
  PM / core: fix typo in documentation
  PM / runtime: Add new helper for conditional usage count incrementation
  MAINTAINERS: Add an entry for the PM core
  PM / runtime: Re-init runtime PM states at probe error and driver unbind
  PM / sleep: prohibit devices probing during suspend/hibernation
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -999,7 +999,7 @@ from its probe routine to make runtime PM work for the device.

It is important to remember that the driver's runtime_suspend() callback
may be executed right after the usage counter has been decremented, because
user space may already have cuased the pm_runtime_allow() helper function
user space may already have caused the pm_runtime_allow() helper function
unblocking the runtime PM of the device to run via sysfs, so the driver must
be prepared to cope with that.

+6 −0
Original line number Diff line number Diff line
@@ -371,6 +371,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
    - increment the device's usage counter, run pm_runtime_resume(dev) and
      return its result

  int pm_runtime_get_if_in_use(struct device *dev);
    - return -EINVAL if 'power.disable_depth' is nonzero; otherwise, if the
      runtime PM status is RPM_ACTIVE and the runtime PM usage counter is
      nonzero, increment the counter and return 1; otherwise return 0 without
      changing the counter

  void pm_runtime_put_noidle(struct device *dev);
    - decrement the device's usage counter

+11 −0
Original line number Diff line number Diff line
@@ -8447,6 +8447,17 @@ F: fs/timerfd.c
F:	include/linux/timer*
F:	kernel/time/*timer*

POWER MANAGEMENT CORE
M:	"Rafael J. Wysocki" <rjw@rjwysocki.net>
L:	linux-pm@vger.kernel.org
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
S:	Supported
F:	drivers/base/power/
F:	include/linux/pm.h
F:	include/linux/pm_*
F:	include/linux/powercap.h
F:	drivers/powercap/

POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
M:	Sebastian Reichel <sre@kernel.org>
M:	Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+2 −0
Original line number Diff line number Diff line
@@ -131,6 +131,8 @@ extern void device_remove_groups(struct device *dev,
extern char *make_class_name(const char *name, struct kobject *kobj);

extern int devres_release_all(struct device *dev);
extern void device_block_probing(void);
extern void device_unblock_probing(void);

/* /sys/devices directory */
extern struct kset *devices_kset;
+49 −1
Original line number Diff line number Diff line
@@ -54,6 +54,13 @@ static LIST_HEAD(deferred_probe_active_list);
static struct workqueue_struct *deferred_wq;
static atomic_t deferred_trigger_count = ATOMIC_INIT(0);

/*
 * In some cases, like suspend to RAM or hibernation, It might be reasonable
 * to prohibit probing of devices as it could be unsafe.
 * Once defer_all_probes is true all drivers probes will be forcibly deferred.
 */
static bool defer_all_probes;

/*
 * deferred_probe_work_func() - Retry probing devices in the active list.
 */
@@ -171,6 +178,30 @@ static void driver_deferred_probe_trigger(void)
	queue_work(deferred_wq, &deferred_probe_work);
}

/**
 * device_block_probing() - Block/defere device's probes
 *
 *	It will disable probing of devices and defer their probes instead.
 */
void device_block_probing(void)
{
	defer_all_probes = true;
	/* sync with probes to avoid races. */
	wait_for_device_probe();
}

/**
 * device_unblock_probing() - Unblock/enable device's probes
 *
 *	It will restore normal behavior and trigger re-probing of deferred
 * devices.
 */
void device_unblock_probing(void)
{
	defer_all_probes = false;
	driver_deferred_probe_trigger();
}

/**
 * deferred_probe_initcall() - Enable probing of deferred devices
 *
@@ -280,9 +311,20 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);

static int really_probe(struct device *dev, struct device_driver *drv)
{
	int ret = 0;
	int ret = -EPROBE_DEFER;
	int local_trigger_count = atomic_read(&deferred_trigger_count);

	if (defer_all_probes) {
		/*
		 * Value of defer_all_probes can be set only by
		 * device_defer_all_probes_enable() which, in turn, will call
		 * wait_for_device_probe() right after that to avoid any races.
		 */
		dev_dbg(dev, "Driver %s force probe deferral\n", drv->name);
		driver_deferred_probe_add(dev);
		return ret;
	}

	atomic_inc(&probe_count);
	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
		 drv->bus->name, __func__, drv->name, dev_name(dev));
@@ -347,6 +389,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
	dev_set_drvdata(dev, NULL);
	if (dev->pm_domain && dev->pm_domain->dismiss)
		dev->pm_domain->dismiss(dev);
	pm_runtime_reinit(dev);

	switch (ret) {
	case -EPROBE_DEFER:
@@ -400,6 +443,10 @@ int driver_probe_done(void)
 */
void wait_for_device_probe(void)
{
	/* wait for the deferred probe workqueue to finish */
	if (driver_deferred_probe_enable)
		flush_workqueue(deferred_wq);

	/* wait for the known devices to complete their probing */
	wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
	async_synchronize_full();
@@ -702,6 +749,7 @@ static void __device_release_driver(struct device *dev)
		dev_set_drvdata(dev, NULL);
		if (dev->pm_domain && dev->pm_domain->dismiss)
			dev->pm_domain->dismiss(dev);
		pm_runtime_reinit(dev);

		klist_remove(&dev->p->knode_driver);
		if (dev->bus)
Loading