linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: Ming Lei <tom.leiming@gmail.com>,
	linux-pci@vger.kernel.org, USB list <linux-usb@vger.kernel.org>,
	Linux PM list <linux-pm@vger.kernel.org>
Subject: Re: Do we need asynchronous pm_runtime_get()? (was: Re: bisected regression ...)
Date: Sun, 5 Aug 2012 17:26:22 +0200	[thread overview]
Message-ID: <201208051726.22729.rjw@sisk.pl> (raw)
In-Reply-To: <Pine.LNX.4.44L0.1208041806490.23711-100000@netrider.rowland.org>

On Sunday, August 05, 2012, Alan Stern wrote:
> On Sat, 4 Aug 2012, Rafael J. Wysocki wrote:
> 
> > On Saturday, August 04, 2012, Alan Stern wrote:
> > > On Sat, 4 Aug 2012, Rafael J. Wysocki wrote:
> > > 
> > > > > That wasn't what he meant.  What if the code needs to run in the _same_
> > > > > context as the caller?  For example, with a spinlock held.
> > > > 
> > > > I see.  I think it wouldn't be unreasonable to require that func should take
> > > > all of the necessary locks by itself.
> > > 
> > > But then if func was called directly, because the device was at full
> > > power, it would deadlock trying to acquire a lock the caller already
> > > holds.
> > 
> > I wonder why the caller may want to take any locks beforehand?
> 
> Who knows?  :-)
> 
> The best answer may be for the caller not to hold any locks.  In the
> runtime-PM document's example driver, the lock would be dropped before
> the resume-and-call.
> 
> > > Do you have any better suggestions?
> > 
> > Hmm.  What about pm_runtime_get_and_call(dev, func_sync, func_async), where
> > func_sync() is to be called if the device is already active and func_async()
> > is to be called if it has to be resumed from the workqueue?
> 
> That's a little better but not much.  It would require storing two 
> function pointers in the dev->power structure.

I don't really think we'll need to store func_sync in dev->power.  At least
I don't see a reason to do that at the moment.

I also think that func_sync() would have to be called if runtime PM is
disabled for the given device, so that callers don't have to check that
condition themselves.

What about the appended experimental patch?

Rafael


---
 drivers/base/power/runtime.c |   82 +++++++++++++++++++++++++++++++++++++++----
 include/linux/pm.h           |    1 
 include/linux/pm_runtime.h   |   14 +++++++
 3 files changed, 90 insertions(+), 7 deletions(-)

Index: linux/drivers/base/power/runtime.c
===================================================================
--- linux.orig/drivers/base/power/runtime.c
+++ linux/drivers/base/power/runtime.c
@@ -484,6 +484,15 @@ static int rpm_suspend(struct device *de
 	goto out;
 }
 
+void rpm_queue_up_resume(struct device *dev)
+{
+	dev->power.request = RPM_REQ_RESUME;
+	if (!dev->power.request_pending) {
+		dev->power.request_pending = true;
+		queue_work(pm_wq, &dev->power.work);
+	}
+}
+
 /**
  * rpm_resume - Carry out runtime resume of given device.
  * @dev: Device to resume.
@@ -524,7 +533,9 @@ static int rpm_resume(struct device *dev
 	 * rather than cancelling it now only to restart it again in the near
 	 * future.
 	 */
-	dev->power.request = RPM_REQ_NONE;
+	if (dev->power.request != RPM_REQ_RESUME || !dev->power.func)
+		dev->power.request = RPM_REQ_NONE;
+
 	if (!dev->power.timer_autosuspends)
 		pm_runtime_deactivate_timer(dev);
 
@@ -533,6 +544,12 @@ static int rpm_resume(struct device *dev
 		goto out;
 	}
 
+	if (dev->power.func && (rpmflags & RPM_ASYNC)) {
+		rpm_queue_up_resume(dev);
+		retval = 0;
+		goto out;
+	}
+
 	if (dev->power.runtime_status == RPM_RESUMING
 	    || dev->power.runtime_status == RPM_SUSPENDING) {
 		DEFINE_WAIT(wait);
@@ -591,11 +608,7 @@ static int rpm_resume(struct device *dev
 
 	/* Carry out an asynchronous or a synchronous resume. */
 	if (rpmflags & RPM_ASYNC) {
-		dev->power.request = RPM_REQ_RESUME;
-		if (!dev->power.request_pending) {
-			dev->power.request_pending = true;
-			queue_work(pm_wq, &dev->power.work);
-		}
+		rpm_queue_up_resume(dev);
 		retval = 0;
 		goto out;
 	}
@@ -691,6 +704,7 @@ static int rpm_resume(struct device *dev
 static void pm_runtime_work(struct work_struct *work)
 {
 	struct device *dev = container_of(work, struct device, power.work);
+	void (*func)(struct device *) = NULL;
 	enum rpm_request req;
 
 	spin_lock_irq(&dev->power.lock);
@@ -715,12 +729,24 @@ static void pm_runtime_work(struct work_
 		rpm_suspend(dev, RPM_NOWAIT | RPM_AUTO);
 		break;
 	case RPM_REQ_RESUME:
-		rpm_resume(dev, RPM_NOWAIT);
+		func = dev->power.func;
+		if (func) {
+			dev->power.func = NULL;
+			pm_runtime_get_noresume(dev);
+			rpm_resume(dev, 0);
+		} else {
+			rpm_resume(dev, RPM_NOWAIT);
+		}
 		break;
 	}
 
  out:
 	spin_unlock_irq(&dev->power.lock);
+
+	if (func) {
+		func(dev);
+		pm_runtime_put(dev);
+	}
 }
 
 /**
@@ -877,6 +903,48 @@ int __pm_runtime_resume(struct device *d
 }
 EXPORT_SYMBOL_GPL(__pm_runtime_resume);
 
+int pm_runtime_get_and_call(struct device *dev, void (*func)(struct device *),
+			     void (*func_async)(struct device *))
+{
+	unsigned long flags;
+	int ret;
+
+	atomic_inc(&dev->power.usage_count);
+
+	spin_lock_irqsave(&dev->power.lock, flags);
+
+	ret = dev->power.runtime_error;
+	if (ret) {
+		func = NULL;
+		goto out;
+	}
+
+	if (dev->power.runtime_status != RPM_ACTIVE
+	    && dev->power.disable_depth == 0)
+		func = NULL;
+
+	if (!func && func_async) {
+		if (dev->power.func) {
+			ret = -EAGAIN;
+			goto out;
+		} else {
+			dev->power.func = func_async;
+		}
+	}
+
+	rpm_resume(dev, RPM_ASYNC);
+
+ out:
+	spin_unlock_irqrestore(&dev->power.lock, flags);
+
+	if (func) {
+		func(dev);
+		return 1;
+	}
+
+	return ret;
+}
+
 /**
  * __pm_runtime_set_status - Set runtime PM status of a device.
  * @dev: Device to handle.
Index: linux/include/linux/pm.h
===================================================================
--- linux.orig/include/linux/pm.h
+++ linux/include/linux/pm.h
@@ -547,6 +547,7 @@ struct dev_pm_info {
 	unsigned long		suspended_jiffies;
 	unsigned long		accounting_timestamp;
 	struct dev_pm_qos_request *pq_req;
+	void			(*func)(struct device *);
 #endif
 	struct pm_subsys_data	*subsys_data;  /* Owned by the subsystem. */
 	struct pm_qos_constraints *constraints;
Index: linux/include/linux/pm_runtime.h
===================================================================
--- linux.orig/include/linux/pm_runtime.h
+++ linux/include/linux/pm_runtime.h
@@ -47,6 +47,9 @@ extern void pm_runtime_set_autosuspend_d
 extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
 extern void pm_runtime_update_max_time_suspended(struct device *dev,
 						 s64 delta_ns);
+extern int pm_runtime_get_and_call(struct device *dev,
+				   void (*func)(struct device *),
+				   void (*func_async)(struct device *));
 
 static inline bool pm_children_suspended(struct device *dev)
 {
@@ -150,6 +153,17 @@ static inline void pm_runtime_set_autosu
 static inline unsigned long pm_runtime_autosuspend_expiration(
 				struct device *dev) { return 0; }
 
+static inline int pm_runtime_get_and_call(struct device *dev,
+					  void (*func)(struct device *),
+					  void (*func_async)(struct device *))
+{
+	if (func) {
+		func(dev);
+		return 1;
+	}
+	return 0;
+}
+
 #endif /* !CONFIG_PM_RUNTIME */
 
 static inline int pm_runtime_idle(struct device *dev)

  reply	other threads:[~2012-08-05 15:20 UTC|newest]

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <Pine.LNX.4.44L0.1207241312050.1164-100000@iolanthe.rowland.org>
     [not found] ` <87r4s0opck.fsf@nemi.mork.no>
2012-07-25  4:08   ` bisected regression, v3.5 -> next-20120724: PCI PM causes USB hotplug failure Bjørn Mork
2012-07-25  4:34     ` Huang Ying
2012-07-25  9:58       ` Bjørn Mork
2012-07-25 13:30         ` huang ying
2012-07-25 13:58           ` Bjørn Mork
2012-07-25 18:56             ` Rafael J. Wysocki
2012-07-25 20:02             ` Rafael J. Wysocki
2012-07-25 22:36               ` Bjørn Mork
2012-07-26  2:38                 ` Huang Ying
2012-07-26  2:38               ` Huang Ying
2012-07-26  8:54             ` Huang Ying
2012-07-26 10:35               ` Bjørn Mork
2012-07-26 11:02                 ` Bjørn Mork
2012-07-26 12:04                   ` Bjørn Mork
2012-07-26 15:03                 ` Alan Stern
2012-07-26 16:24                   ` Bjørn Mork
2012-07-27  5:35                 ` Huang Ying
2012-07-27  9:11                   ` Bjørn Mork
2012-07-30  3:15                     ` Huang Ying
2012-07-30  8:08                       ` Bjørn Mork
2012-07-30 13:31                         ` huang ying
2012-07-30 16:57                           ` Bjørn Mork
2012-07-31  0:22                             ` Huang Ying
2012-07-30 14:19                       ` Alan Stern
2012-07-31  0:24                         ` Huang Ying
2012-07-31  3:18                         ` Huang Ying
2012-07-31 17:07                           ` Alan Stern
2012-07-27 15:03                   ` Alan Stern
2012-07-27 19:11                     ` Rafael J. Wysocki
2012-07-27 19:39                       ` Alan Stern
2012-07-27 19:54                         ` Rafael J. Wysocki
2012-07-28 16:12                           ` Alan Stern
2012-07-28 20:26                             ` Rafael J. Wysocki
2012-07-28 21:12                               ` Alan Stern
2012-07-29 13:55                                 ` Rafael J. Wysocki
2012-07-29 14:55                                   ` Alan Stern
2012-07-29 19:18                                     ` Rafael J. Wysocki
2012-07-31 20:31                                       ` Do we need asynchronous pm_runtime_get()? (was: Re: bisected regression ...) Rafael J. Wysocki
2012-07-31 21:05                                         ` Alan Stern
2012-07-31 21:34                                           ` Rafael J. Wysocki
2012-07-31 21:49                                             ` Rafael J. Wysocki
2012-08-01 14:36                                             ` Alan Stern
2012-08-01 21:24                                               ` Rafael J. Wysocki
2012-08-02 20:16                                                 ` Alan Stern
2012-08-02 21:26                                                   ` Rafael J. Wysocki
2012-08-03  2:20                                                     ` Alan Stern
2012-08-03  3:37                                                       ` Ming Lei
2012-08-03 14:28                                                         ` Alan Stern
2012-08-04 19:47                                                         ` Rafael J. Wysocki
2012-08-04 20:25                                                           ` Alan Stern
2012-08-04 20:48                                                             ` Rafael J. Wysocki
2012-08-04 20:48                                                               ` Alan Stern
2012-08-04 21:15                                                                 ` Rafael J. Wysocki
2012-08-04 22:13                                                                   ` Alan Stern
2012-08-05 15:26                                                                     ` Rafael J. Wysocki [this message]
2012-08-06 13:30                                                                       ` Ming Lei
2012-08-06 14:47                                                                         ` Alan Stern
2012-08-07  1:35                                                                           ` Ming Lei
2012-08-07 11:23                                                                             ` Rafael J. Wysocki
2012-08-07 15:14                                                                               ` Ming Lei
2012-08-07 15:42                                                                                 ` Alan Stern
2012-08-07 16:30                                                                                   ` Ming Lei
2012-08-07 20:57                                                                                     ` Rafael J. Wysocki
2012-08-07 20:45                                                                                 ` Rafael J. Wysocki
2012-08-08  2:02                                                                                   ` Ming Lei
2012-08-08 18:42                                                                                     ` Alan Stern
2012-08-08 20:16                                                                                       ` Rafael J. Wysocki
2012-08-09  5:55                                                                                         ` Ming Lei
2012-08-09 10:46                                                                                           ` Rafael J. Wysocki
2012-08-09 10:55                                                                                             ` Ming Lei
2012-08-09 19:41                                                                                               ` Rafael J. Wysocki
2012-08-10  3:19                                                                                                 ` Ming Lei
2012-08-10 20:29                                                                                                   ` Rafael J. Wysocki
2012-08-08 22:27                                                                                     ` Rafael J. Wysocki
2012-08-06 15:48                                                                       ` Alan Stern
2012-08-06 20:30                                                                         ` Rafael J. Wysocki
2012-08-07 12:28                                                                           ` Rafael J. Wysocki
2012-08-07 17:15                                                                             ` Alan Stern
2012-08-07 21:31                                                                               ` Rafael J. Wysocki
2012-08-03 14:05                                                       ` Alan Stern
2012-08-04 20:08                                                         ` Rafael J. Wysocki
2012-08-04 20:42                                                           ` Alan Stern
2012-08-04 20:59                                                             ` Rafael J. Wysocki
2012-08-04 19:35                                                       ` Rafael J. Wysocki
2012-07-29 20:12                                     ` bisected regression, v3.5 -> next-20120724: PCI PM causes USB hotplug failure Jassi Brar
2012-07-29 21:44                                       ` Alan Stern
2012-07-25 19:51           ` [PATCH] PCI / PM: Fix messages printed by acpi_pci_set_power_state() Rafael J. Wysocki
2012-07-25 20:02             ` Alan Stern
2012-07-25 20:48               ` [PATCH][update] " Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201208051726.22729.rjw@sisk.pl \
    --to=rjw@sisk.pl \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=stern@rowland.harvard.edu \
    --cc=tom.leiming@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).