diff options
Diffstat (limited to 'drivers/base/power/runtime.c')
| -rw-r--r-- | drivers/base/power/runtime.c | 47 | 
1 files changed, 19 insertions, 28 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 7bcf80fa9ada..6e89b51ea3d9 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -134,11 +134,11 @@ unsigned long pm_runtime_autosuspend_expiration(struct device *dev)  	if (!dev->power.use_autosuspend)  		goto out; -	autosuspend_delay = ACCESS_ONCE(dev->power.autosuspend_delay); +	autosuspend_delay = READ_ONCE(dev->power.autosuspend_delay);  	if (autosuspend_delay < 0)  		goto out; -	last_busy = ACCESS_ONCE(dev->power.last_busy); +	last_busy = READ_ONCE(dev->power.last_busy);  	elapsed = jiffies - last_busy;  	if (elapsed < 0)  		goto out;	/* jiffies has wrapped around. */ @@ -253,7 +253,7 @@ static int rpm_check_suspend_allowed(struct device *dev)  	    || (dev->power.request_pending  			&& dev->power.request == RPM_REQ_RESUME))  		retval = -EAGAIN; -	else if (__dev_pm_qos_read_value(dev) < 0) +	else if (__dev_pm_qos_read_value(dev) == 0)  		retval = -EPERM;  	else if (dev->power.runtime_status == RPM_SUSPENDED)  		retval = 1; @@ -276,7 +276,8 @@ static int rpm_get_suppliers(struct device *dev)  			continue;  		retval = pm_runtime_get_sync(link->supplier); -		if (retval < 0) { +		/* Ignore suppliers with disabled runtime PM. */ +		if (retval < 0 && retval != -EACCES) {  			pm_runtime_put_noidle(link->supplier);  			return retval;  		} @@ -894,9 +895,9 @@ static void pm_runtime_work(struct work_struct *work)   *   * Check if the time is right and queue a suspend request.   */ -static void pm_suspend_timer_fn(unsigned long data) +static void pm_suspend_timer_fn(struct timer_list *t)  { -	struct device *dev = (struct device *)data; +	struct device *dev = from_timer(dev, t, power.suspend_timer);  	unsigned long flags;  	unsigned long expires; @@ -1101,29 +1102,13 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)  		goto out;  	} -	if (dev->power.runtime_status == status) +	if (dev->power.runtime_status == status || !parent)  		goto out_set;  	if (status == RPM_SUSPENDED) { -		/* -		 * It is invalid to suspend a device with an active child, -		 * unless it has been set to ignore its children. -		 */ -		if (!dev->power.ignore_children && -			atomic_read(&dev->power.child_count)) { -			dev_err(dev, "runtime PM trying to suspend device but active child\n"); -			error = -EBUSY; -			goto out; -		} - -		if (parent) { -			atomic_add_unless(&parent->power.child_count, -1, 0); -			notify_parent = !parent->power.ignore_children; -		} -		goto out_set; -	} - -	if (parent) { +		atomic_add_unless(&parent->power.child_count, -1, 0); +		notify_parent = !parent->power.ignore_children; +	} else {  		spin_lock_nested(&parent->power.lock, SINGLE_DEPTH_NESTING);  		/* @@ -1307,6 +1292,13 @@ void pm_runtime_enable(struct device *dev)  	else  		dev_warn(dev, "Unbalanced %s!\n", __func__); +	WARN(!dev->power.disable_depth && +	     dev->power.runtime_status == RPM_SUSPENDED && +	     !dev->power.ignore_children && +	     atomic_read(&dev->power.child_count) > 0, +	     "Enabling runtime PM for inactive device (%s) with active children\n", +	     dev_name(dev)); +  	spin_unlock_irqrestore(&dev->power.lock, flags);  }  EXPORT_SYMBOL_GPL(pm_runtime_enable); @@ -1499,8 +1491,7 @@ void pm_runtime_init(struct device *dev)  	INIT_WORK(&dev->power.work, pm_runtime_work);  	dev->power.timer_expires = 0; -	setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn, -			(unsigned long)dev); +	timer_setup(&dev->power.suspend_timer, pm_suspend_timer_fn, 0);  	init_waitqueue_head(&dev->power.wait_queue);  }  | 

