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

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

Merge branch 'pm-domains'

* pm-domains:
  PM / Domains: Fix computation of maximum domain off time
  PM / Domains: Fix link checking when add subdomain
  PM / Domains: Cache device stop and domain power off governor results, v3
  PM / Domains: Make device removal more straightforward
  PM / QoS: Create device constraints objects on notifier registration
  PM / Runtime: Remove device fields related to suspend time, v2
  PM / Domains: Rework default domain power off governor function, v2
  PM / Domains: Rework default device stop governor function, v2
parents 3a9da04a b723b0eb
Loading
Loading
Loading
Loading
+111 −40
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/io.h>
#include <linux/pm_runtime.h>
#include <linux/pm_domain.h>
#include <linux/pm_qos.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/sched.h>
@@ -38,11 +39,13 @@
	ktime_t __start = ktime_get();						\
	type __retval = GENPD_DEV_CALLBACK(genpd, type, callback, dev);		\
	s64 __elapsed = ktime_to_ns(ktime_sub(ktime_get(), __start));		\
	struct generic_pm_domain_data *__gpd_data = dev_gpd_data(dev);		\
	if (__elapsed > __gpd_data->td.field) {					\
		__gpd_data->td.field = __elapsed;				\
	struct gpd_timing_data *__td = &dev_gpd_data(dev)->td;			\
	if (!__retval && __elapsed > __td->field) {				\
		__td->field = __elapsed;					\
		dev_warn(dev, name " latency exceeded, new value %lld ns\n",	\
			__elapsed);						\
		genpd->max_off_time_changed = true;				\
		__td->constraint_changed = true;				\
	}									\
	__retval;								\
})
@@ -211,6 +214,7 @@ int __pm_genpd_poweron(struct generic_pm_domain *genpd)
		elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
		if (elapsed_ns > genpd->power_on_latency_ns) {
			genpd->power_on_latency_ns = elapsed_ns;
			genpd->max_off_time_changed = true;
			if (genpd->name)
				pr_warning("%s: Power-on latency exceeded, "
					"new value %lld ns\n", genpd->name,
@@ -247,6 +251,53 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd)

#ifdef CONFIG_PM_RUNTIME

static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
				     unsigned long val, void *ptr)
{
	struct generic_pm_domain_data *gpd_data;
	struct device *dev;

	gpd_data = container_of(nb, struct generic_pm_domain_data, nb);

	mutex_lock(&gpd_data->lock);
	dev = gpd_data->base.dev;
	if (!dev) {
		mutex_unlock(&gpd_data->lock);
		return NOTIFY_DONE;
	}
	mutex_unlock(&gpd_data->lock);

	for (;;) {
		struct generic_pm_domain *genpd;
		struct pm_domain_data *pdd;

		spin_lock_irq(&dev->power.lock);

		pdd = dev->power.subsys_data ?
				dev->power.subsys_data->domain_data : NULL;
		if (pdd) {
			to_gpd_data(pdd)->td.constraint_changed = true;
			genpd = dev_to_genpd(dev);
		} else {
			genpd = ERR_PTR(-ENODATA);
		}

		spin_unlock_irq(&dev->power.lock);

		if (!IS_ERR(genpd)) {
			mutex_lock(&genpd->lock);
			genpd->max_off_time_changed = true;
			mutex_unlock(&genpd->lock);
		}

		dev = dev->parent;
		if (!dev || dev->power.ignore_children)
			break;
	}

	return NOTIFY_DONE;
}

/**
 * __pm_genpd_save_device - Save the pre-suspend state of a device.
 * @pdd: Domain data of the device to save the state of.
@@ -435,6 +486,7 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
		elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
		if (elapsed_ns > genpd->power_off_latency_ns) {
			genpd->power_off_latency_ns = elapsed_ns;
			genpd->max_off_time_changed = true;
			if (genpd->name)
				pr_warning("%s: Power-off latency exceeded, "
					"new value %lld ns\n", genpd->name,
@@ -443,17 +495,6 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
	}

	genpd->status = GPD_STATE_POWER_OFF;
	genpd->power_off_time = ktime_get();

	/* Update PM QoS information for devices in the domain. */
	list_for_each_entry_reverse(pdd, &genpd->dev_list, list_node) {
		struct gpd_timing_data *td = &to_gpd_data(pdd)->td;

		pm_runtime_update_max_time_suspended(pdd->dev,
					td->start_latency_ns +
					td->restore_state_latency_ns +
					genpd->power_on_latency_ns);
	}

	list_for_each_entry(link, &genpd->slave_links, slave_node) {
		genpd_sd_counter_dec(link->master);
@@ -514,9 +555,6 @@ static int pm_genpd_runtime_suspend(struct device *dev)
	if (ret)
		return ret;

	pm_runtime_update_max_time_suspended(dev,
				dev_gpd_data(dev)->td.start_latency_ns);

	/*
	 * If power.irq_safe is set, this routine will be run with interrupts
	 * off, so it can't use mutexes.
@@ -613,6 +651,12 @@ void pm_genpd_poweroff_unused(void)

#else

static inline int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
					    unsigned long val, void *ptr)
{
	return NOTIFY_DONE;
}

static inline void genpd_power_off_work_fn(struct work_struct *work) {}

#define pm_genpd_runtime_suspend	NULL
@@ -1209,6 +1253,14 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
		return -EINVAL;

	gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
	if (!gpd_data)
		return -ENOMEM;

	mutex_init(&gpd_data->lock);
	gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier;
	dev_pm_qos_add_notifier(dev, &gpd_data->nb);

	genpd_acquire_lock(genpd);

	if (genpd->status == GPD_STATE_POWER_OFF) {
@@ -1227,26 +1279,35 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
			goto out;
		}

	gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
	if (!gpd_data) {
		ret = -ENOMEM;
		goto out;
	}

	genpd->device_count++;
	genpd->max_off_time_changed = true;

	dev->pm_domain = &genpd->domain;
	dev_pm_get_subsys_data(dev);

	mutex_lock(&gpd_data->lock);
	spin_lock_irq(&dev->power.lock);
	dev->pm_domain = &genpd->domain;
	dev->power.subsys_data->domain_data = &gpd_data->base;
	gpd_data->base.dev = dev;
	gpd_data->need_restore = false;
	list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
	gpd_data->need_restore = false;
	if (td)
		gpd_data->td = *td;

	gpd_data->td.constraint_changed = true;
	gpd_data->td.effective_constraint_ns = -1;
	spin_unlock_irq(&dev->power.lock);
	mutex_unlock(&gpd_data->lock);

	genpd_release_lock(genpd);

	return 0;

 out:
	genpd_release_lock(genpd);

	dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
	kfree(gpd_data);
	return ret;
}

@@ -1290,12 +1351,15 @@ int __pm_genpd_of_add_device(struct device_node *genpd_node, struct device *dev,
int pm_genpd_remove_device(struct generic_pm_domain *genpd,
			   struct device *dev)
{
	struct generic_pm_domain_data *gpd_data;
	struct pm_domain_data *pdd;
	int ret = -EINVAL;
	int ret = 0;

	dev_dbg(dev, "%s()\n", __func__);

	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev)
	    ||  IS_ERR_OR_NULL(dev->pm_domain)
	    ||  pd_to_genpd(dev->pm_domain) != genpd)
		return -EINVAL;

	genpd_acquire_lock(genpd);
@@ -1305,21 +1369,27 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
		goto out;
	}

	list_for_each_entry(pdd, &genpd->dev_list, list_node) {
		if (pdd->dev != dev)
			continue;
	genpd->device_count--;
	genpd->max_off_time_changed = true;

	spin_lock_irq(&dev->power.lock);
	dev->pm_domain = NULL;
	pdd = dev->power.subsys_data->domain_data;
	list_del_init(&pdd->list_node);
	dev->power.subsys_data->domain_data = NULL;
	spin_unlock_irq(&dev->power.lock);

	gpd_data = to_gpd_data(pdd);
	mutex_lock(&gpd_data->lock);
	pdd->dev = NULL;
		dev_pm_put_subsys_data(dev);
		dev->pm_domain = NULL;
		kfree(to_gpd_data(pdd));
	mutex_unlock(&gpd_data->lock);

		genpd->device_count--;
	genpd_release_lock(genpd);

		ret = 0;
		break;
	}
	dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
	kfree(gpd_data);
	dev_pm_put_subsys_data(dev);
	return 0;

 out:
	genpd_release_lock(genpd);
@@ -1378,7 +1448,7 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
		goto out;
	}

	list_for_each_entry(link, &genpd->slave_links, slave_node) {
	list_for_each_entry(link, &genpd->master_links, master_node) {
		if (link->slave == subdomain && link->master == genpd) {
			ret = -EINVAL;
			goto out;
@@ -1690,6 +1760,7 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
	genpd->resume_count = 0;
	genpd->device_count = 0;
	genpd->max_off_time_ns = -1;
	genpd->max_off_time_changed = true;
	genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
	genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
	genpd->domain.ops.runtime_idle = pm_generic_runtime_idle;
+125 −41
Original line number Diff line number Diff line
@@ -14,6 +14,31 @@

#ifdef CONFIG_PM_RUNTIME

static int dev_update_qos_constraint(struct device *dev, void *data)
{
	s64 *constraint_ns_p = data;
	s32 constraint_ns = -1;

	if (dev->power.subsys_data && dev->power.subsys_data->domain_data)
		constraint_ns = dev_gpd_data(dev)->td.effective_constraint_ns;

	if (constraint_ns < 0) {
		constraint_ns = dev_pm_qos_read_value(dev);
		constraint_ns *= NSEC_PER_USEC;
	}
	if (constraint_ns == 0)
		return 0;

	/*
	 * constraint_ns cannot be negative here, because the device has been
	 * suspended.
	 */
	if (constraint_ns < *constraint_ns_p || *constraint_ns_p == 0)
		*constraint_ns_p = constraint_ns;

	return 0;
}

/**
 * default_stop_ok - Default PM domain governor routine for stopping devices.
 * @dev: Device to check.
@@ -21,14 +46,52 @@
bool default_stop_ok(struct device *dev)
{
	struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
	unsigned long flags;
	s64 constraint_ns;

	dev_dbg(dev, "%s()\n", __func__);

	if (dev->power.max_time_suspended_ns < 0 || td->break_even_ns == 0)
		return true;
	spin_lock_irqsave(&dev->power.lock, flags);

	if (!td->constraint_changed) {
		bool ret = td->cached_stop_ok;

	return td->stop_latency_ns + td->start_latency_ns < td->break_even_ns
		&& td->break_even_ns < dev->power.max_time_suspended_ns;
		spin_unlock_irqrestore(&dev->power.lock, flags);
		return ret;
	}
	td->constraint_changed = false;
	td->cached_stop_ok = false;
	td->effective_constraint_ns = -1;
	constraint_ns = __dev_pm_qos_read_value(dev);

	spin_unlock_irqrestore(&dev->power.lock, flags);

	if (constraint_ns < 0)
		return false;

	constraint_ns *= NSEC_PER_USEC;
	/*
	 * We can walk the children without any additional locking, because
	 * they all have been suspended at this point and their
	 * effective_constraint_ns fields won't be modified in parallel with us.
	 */
	if (!dev->power.ignore_children)
		device_for_each_child(dev, &constraint_ns,
				      dev_update_qos_constraint);

	if (constraint_ns > 0) {
		constraint_ns -= td->start_latency_ns;
		if (constraint_ns == 0)
			return false;
	}
	td->effective_constraint_ns = constraint_ns;
	td->cached_stop_ok = constraint_ns > td->stop_latency_ns ||
				constraint_ns == 0;
	/*
	 * The children have been suspended already, so we don't need to take
	 * their stop latencies into account here.
	 */
	return td->cached_stop_ok;
}

/**
@@ -42,9 +105,27 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
	struct generic_pm_domain *genpd = pd_to_genpd(pd);
	struct gpd_link *link;
	struct pm_domain_data *pdd;
	s64 min_dev_off_time_ns;
	s64 min_off_time_ns;
	s64 off_on_time_ns;
	ktime_t time_now = ktime_get();

	if (genpd->max_off_time_changed) {
		struct gpd_link *link;

		/*
		 * We have to invalidate the cached results for the masters, so
		 * use the observation that default_power_down_ok() is not
		 * going to be called for any master until this instance
		 * returns.
		 */
		list_for_each_entry(link, &genpd->slave_links, slave_node)
			link->master->max_off_time_changed = true;

		genpd->max_off_time_changed = false;
		genpd->cached_power_down_ok = false;
		genpd->max_off_time_ns = -1;
	} else {
		return genpd->cached_power_down_ok;
	}

	off_on_time_ns = genpd->power_off_latency_ns +
				genpd->power_on_latency_ns;
@@ -61,6 +142,7 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
				to_gpd_data(pdd)->td.save_state_latency_ns;
	}

	min_off_time_ns = -1;
	/*
	 * Check if subdomains can be off for enough time.
	 *
@@ -73,8 +155,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
		if (sd_max_off_ns < 0)
			continue;

		sd_max_off_ns -= ktime_to_ns(ktime_sub(time_now,
						       sd->power_off_time));
		/*
		 * Check if the subdomain is allowed to be off long enough for
		 * the current domain to turn off and on (that's how much time
@@ -82,60 +162,64 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
		 */
		if (sd_max_off_ns <= off_on_time_ns)
			return false;

		if (min_off_time_ns > sd_max_off_ns || min_off_time_ns < 0)
			min_off_time_ns = sd_max_off_ns;
	}

	/*
	 * Check if the devices in the domain can be off enough time.
	 */
	min_dev_off_time_ns = -1;
	list_for_each_entry(pdd, &genpd->dev_list, list_node) {
		struct gpd_timing_data *td;
		struct device *dev = pdd->dev;
		s64 dev_off_time_ns;
		s64 constraint_ns;

		if (!dev->driver || dev->power.max_time_suspended_ns < 0)
		if (!pdd->dev->driver)
			continue;

		/*
		 * Check if the device is allowed to be off long enough for the
		 * domain to turn off and on (that's how much time it will
		 * have to wait worst case).
		 */
		td = &to_gpd_data(pdd)->td;
		dev_off_time_ns = dev->power.max_time_suspended_ns -
			(td->start_latency_ns + td->restore_state_latency_ns +
				ktime_to_ns(ktime_sub(time_now,
						dev->power.suspend_time)));
		if (dev_off_time_ns <= off_on_time_ns)
			return false;

		if (min_dev_off_time_ns > dev_off_time_ns
		    || min_dev_off_time_ns < 0)
			min_dev_off_time_ns = dev_off_time_ns;
		constraint_ns = td->effective_constraint_ns;
		/* default_stop_ok() need not be called before us. */
		if (constraint_ns < 0) {
			constraint_ns = dev_pm_qos_read_value(pdd->dev);
			constraint_ns *= NSEC_PER_USEC;
		}
		if (constraint_ns == 0)
			continue;

	if (min_dev_off_time_ns < 0) {
		/*
		 * There are no latency constraints, so the domain can spend
		 * arbitrary time in the "off" state.
		 * constraint_ns cannot be negative here, because the device has
		 * been suspended.
		 */
		genpd->max_off_time_ns = -1;
		return true;
		constraint_ns -= td->restore_state_latency_ns;
		if (constraint_ns <= off_on_time_ns)
			return false;

		if (min_off_time_ns > constraint_ns || min_off_time_ns < 0)
			min_off_time_ns = constraint_ns;
	}

	genpd->cached_power_down_ok = true;

	/*
	 * The difference between the computed minimum delta and the time needed
	 * to turn the domain on is the maximum theoretical time this domain can
	 * spend in the "off" state.
	 * If the computed minimum device off time is negative, there are no
	 * latency constraints, so the domain can spend arbitrary time in the
	 * "off" state.
	 */
	min_dev_off_time_ns -= genpd->power_on_latency_ns;
	if (min_off_time_ns < 0)
		return true;

	/*
	 * If the difference between the computed minimum delta and the time
	 * needed to turn the domain off and back on on is smaller than the
	 * domain's power break even time, removing power from the domain is not
	 * worth it.
	 * The difference between the computed minimum subdomain or device off
	 * time and the time needed to turn the domain on is the maximum
	 * theoretical time this domain can spend in the "off" state.
	 */
	if (genpd->break_even_ns >
	    min_dev_off_time_ns - genpd->power_off_latency_ns)
		return false;

	genpd->max_off_time_ns = min_dev_off_time_ns;
	genpd->max_off_time_ns = min_off_time_ns - genpd->power_on_latency_ns;
	return true;
}

+12 −7
Original line number Diff line number Diff line
@@ -352,21 +352,26 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
 *
 * Will register the notifier into a notification chain that gets called
 * upon changes to the target value for the device.
 *
 * If the device's constraints object doesn't exist when this routine is called,
 * it will be created (or error code will be returned if that fails).
 */
int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
{
	int retval = 0;
	int ret = 0;

	mutex_lock(&dev_pm_qos_mtx);

	/* Silently return if the constraints object is not present. */
	if (dev->power.constraints)
		retval = blocking_notifier_chain_register(
				dev->power.constraints->notifiers,
				notifier);
	if (!dev->power.constraints)
		ret = dev->power.power_state.event != PM_EVENT_INVALID ?
			dev_pm_qos_constraints_allocate(dev) : -ENODEV;

	if (!ret)
		ret = blocking_notifier_chain_register(
				dev->power.constraints->notifiers, notifier);

	mutex_unlock(&dev_pm_qos_mtx);
	return retval;
	return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier);

+2 −101
Original line number Diff line number Diff line
@@ -282,47 +282,6 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev)
	return retval != -EACCES ? retval : -EIO;
}

struct rpm_qos_data {
	ktime_t time_now;
	s64 constraint_ns;
};

/**
 * rpm_update_qos_constraint - Update a given PM QoS constraint data.
 * @dev: Device whose timing data to use.
 * @data: PM QoS constraint data to update.
 *
 * Use the suspend timing data of @dev to update PM QoS constraint data pointed
 * to by @data.
 */
static int rpm_update_qos_constraint(struct device *dev, void *data)
{
	struct rpm_qos_data *qos = data;
	unsigned long flags;
	s64 delta_ns;
	int ret = 0;

	spin_lock_irqsave(&dev->power.lock, flags);

	if (dev->power.max_time_suspended_ns < 0)
		goto out;

	delta_ns = dev->power.max_time_suspended_ns -
		ktime_to_ns(ktime_sub(qos->time_now, dev->power.suspend_time));
	if (delta_ns <= 0) {
		ret = -EBUSY;
		goto out;
	}

	if (qos->constraint_ns > delta_ns || qos->constraint_ns == 0)
		qos->constraint_ns = delta_ns;

 out:
	spin_unlock_irqrestore(&dev->power.lock, flags);

	return ret;
}

/**
 * rpm_suspend - Carry out runtime suspend of given device.
 * @dev: Device to suspend.
@@ -349,7 +308,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)
{
	int (*callback)(struct device *);
	struct device *parent = NULL;
	struct rpm_qos_data qos;
	int retval;

	trace_rpm_suspend(dev, rpmflags);
@@ -445,38 +403,14 @@ static int rpm_suspend(struct device *dev, int rpmflags)
		goto out;
	}

	qos.constraint_ns = __dev_pm_qos_read_value(dev);
	if (qos.constraint_ns < 0) {
		/* Negative constraint means "never suspend". */
	if (__dev_pm_qos_read_value(dev) < 0) {
		/* Negative PM QoS constraint means "never suspend". */
		retval = -EPERM;
		goto out;
	}
	qos.constraint_ns *= NSEC_PER_USEC;
	qos.time_now = ktime_get();

	__update_runtime_status(dev, RPM_SUSPENDING);

	if (!dev->power.ignore_children) {
		if (dev->power.irq_safe)
			spin_unlock(&dev->power.lock);
		else
			spin_unlock_irq(&dev->power.lock);

		retval = device_for_each_child(dev, &qos,
					       rpm_update_qos_constraint);

		if (dev->power.irq_safe)
			spin_lock(&dev->power.lock);
		else
			spin_lock_irq(&dev->power.lock);

		if (retval)
			goto fail;
	}

	dev->power.suspend_time = qos.time_now;
	dev->power.max_time_suspended_ns = qos.constraint_ns ? : -1;

	if (dev->pm_domain)
		callback = dev->pm_domain->ops.runtime_suspend;
	else if (dev->type && dev->type->pm)
@@ -529,8 +463,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)

 fail:
	__update_runtime_status(dev, RPM_ACTIVE);
	dev->power.suspend_time = ktime_set(0, 0);
	dev->power.max_time_suspended_ns = -1;
	dev->power.deferred_resume = false;
	wake_up_all(&dev->power.wait_queue);

@@ -704,9 +636,6 @@ static int rpm_resume(struct device *dev, int rpmflags)
	if (dev->power.no_callbacks)
		goto no_callback;	/* Assume success. */

	dev->power.suspend_time = ktime_set(0, 0);
	dev->power.max_time_suspended_ns = -1;

	__update_runtime_status(dev, RPM_RESUMING);

	if (dev->pm_domain)
@@ -1369,9 +1298,6 @@ void pm_runtime_init(struct device *dev)
	setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn,
			(unsigned long)dev);

	dev->power.suspend_time = ktime_set(0, 0);
	dev->power.max_time_suspended_ns = -1;

	init_waitqueue_head(&dev->power.wait_queue);
}

@@ -1389,28 +1315,3 @@ void pm_runtime_remove(struct device *dev)
	if (dev->power.irq_safe && dev->parent)
		pm_runtime_put_sync(dev->parent);
}

/**
 * pm_runtime_update_max_time_suspended - Update device's suspend time data.
 * @dev: Device to handle.
 * @delta_ns: Value to subtract from the device's max_time_suspended_ns field.
 *
 * Update the device's power.max_time_suspended_ns field by subtracting
 * @delta_ns from it.  The resulting value of power.max_time_suspended_ns is
 * never negative.
 */
void pm_runtime_update_max_time_suspended(struct device *dev, s64 delta_ns)
{
	unsigned long flags;

	spin_lock_irqsave(&dev->power.lock, flags);

	if (delta_ns > 0 && dev->power.max_time_suspended_ns > 0) {
		if (dev->power.max_time_suspended_ns > delta_ns)
			dev->power.max_time_suspended_ns -= delta_ns;
		else
			dev->power.max_time_suspended_ns = 0;
	}

	spin_unlock_irqrestore(&dev->power.lock, flags);
}
+0 −2
Original line number Diff line number Diff line
@@ -544,8 +544,6 @@ struct dev_pm_info {
	unsigned long		active_jiffies;
	unsigned long		suspended_jiffies;
	unsigned long		accounting_timestamp;
	ktime_t			suspend_time;
	s64			max_time_suspended_ns;
	struct dev_pm_qos_request *pq_req;
#endif
	struct pm_subsys_data	*subsys_data;  /* Owned by the subsystem. */
Loading