linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] sh-sci / PM: Fix problem with runtime PM callbacks run with interrupts off
@ 2011-08-20 19:31 Rafael J. Wysocki
  2011-08-20 19:32 ` [PATCH 1/2] PM / Runtime: Introduce pm_runtime_irq_unsafe() Rafael J. Wysocki
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Rafael J. Wysocki @ 2011-08-20 19:31 UTC (permalink / raw)
  To: linux-sh; +Cc: Linux PM mailing list, LKML, Magnus Damm

Hi,

The sh-sci driver uses pm_runtime_get/put_sync() in such a way
that they may be run with interrupts off and cause the (recently
added) might_sleep_if() to trigger in rpm_suspend/resume().

To avoid that, it's necessary to set the SCI device's power.irq_safe
flag to indicate that it's runtime PM callbacks may be executed with
interrupts off safely.  However, the sh-sci driver needs to be able to
clear that flag sometimes, so a new runtime PM helper for doing that
is needed.

[1/2] - Add pm_runtime_irq_unsafe() for clearing the power.irq_safe device flag.
[2/2] - Make sh-sci use power.irq_safe to indicate that runtime PM callbacks
        may be run with interrupts off.

Thanks,
Rafael


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/2] PM / Runtime: Introduce pm_runtime_irq_unsafe()
  2011-08-20 19:31 [PATCH 0/2] sh-sci / PM: Fix problem with runtime PM callbacks run with interrupts off Rafael J. Wysocki
@ 2011-08-20 19:32 ` Rafael J. Wysocki
  2011-08-21 14:55   ` [linux-pm] " Alan Stern
  2011-08-20 19:33 ` [PATCH 2/2] sh-sci / PM: Use power.irq_safe Rafael J. Wysocki
  2011-08-21 19:09 ` [PATCH 0/2 v2] sh-sci / PM: Fix problem with runtime PM callbacks run with interrupts off Rafael J. Wysocki
  2 siblings, 1 reply; 12+ messages in thread
From: Rafael J. Wysocki @ 2011-08-20 19:32 UTC (permalink / raw)
  To: linux-sh; +Cc: Linux PM mailing list, LKML, Magnus Damm

From: Rafael J. Wysocki <rjw@sisk.pl>

Add a helper function allowing drivers and subsystems to clear
the power.irq_safe device flag.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 Documentation/power/runtime_pm.txt |    4 ++++
 drivers/base/power/runtime.c       |    9 +++++----
 include/linux/pm_runtime.h         |   13 ++++++++++++-
 3 files changed, 21 insertions(+), 5 deletions(-)

Index: linux/include/linux/pm_runtime.h
===================================================================
--- linux.orig/include/linux/pm_runtime.h
+++ linux/include/linux/pm_runtime.h
@@ -40,7 +40,7 @@ extern int pm_generic_runtime_idle(struc
 extern int pm_generic_runtime_suspend(struct device *dev);
 extern int pm_generic_runtime_resume(struct device *dev);
 extern void pm_runtime_no_callbacks(struct device *dev);
-extern void pm_runtime_irq_safe(struct device *dev);
+extern void __pm_runtime_irq_safe(struct device *dev, bool irq_safe);
 extern void __pm_runtime_use_autosuspend(struct device *dev, bool use);
 extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
 extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
@@ -102,6 +102,16 @@ static inline void pm_runtime_mark_last_
 	ACCESS_ONCE(dev->power.last_busy) = jiffies;
 }
 
+static inline void pm_runtime_irq_safe(struct device *dev)
+{
+	__pm_runtime_irq_safe(dev, true);
+}
+
+static inline void pm_runtime_irq_unsafe(struct device *dev)
+{
+	__pm_runtime_irq_safe(dev, false);
+}
+
 #else /* !CONFIG_PM_RUNTIME */
 
 static inline int __pm_runtime_idle(struct device *dev, int rpmflags)
@@ -143,6 +153,7 @@ static inline int pm_generic_runtime_sus
 static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
 static inline void pm_runtime_no_callbacks(struct device *dev) {}
 static inline void pm_runtime_irq_safe(struct device *dev) {}
+static inline void pm_runtime_irq_unsafe(struct device *dev) {}
 
 static inline bool pm_runtime_callbacks_present(struct device *dev) { return false; }
 static inline void pm_runtime_mark_last_busy(struct device *dev) {}
Index: linux/drivers/base/power/runtime.c
===================================================================
--- linux.orig/drivers/base/power/runtime.c
+++ linux/drivers/base/power/runtime.c
@@ -1109,22 +1109,23 @@ void pm_runtime_no_callbacks(struct devi
 EXPORT_SYMBOL_GPL(pm_runtime_no_callbacks);
 
 /**
- * pm_runtime_irq_safe - Leave interrupts disabled during callbacks.
+ * __pm_runtime_irq_safe - Manipulate a device's power.irq_safe flag.
  * @dev: Device to handle
+ * @irq_safe: Whether or not to leave interrupts disabled during callbacks.
  *
- * Set the power.irq_safe flag, which tells the PM core that the
+ * Set or unset the power.irq_safe flag, which tells the PM core that the
  * ->runtime_suspend() and ->runtime_resume() callbacks for this device should
  * always be invoked with the spinlock held and interrupts disabled.  It also
  * causes the parent's usage counter to be permanently incremented, preventing
  * the parent from runtime suspending -- otherwise an irq-safe child might have
  * to wait for a non-irq-safe parent.
  */
-void pm_runtime_irq_safe(struct device *dev)
+void __pm_runtime_irq_safe(struct device *dev, bool irq_safe)
 {
 	if (dev->parent)
 		pm_runtime_get_sync(dev->parent);
 	spin_lock_irq(&dev->power.lock);
-	dev->power.irq_safe = 1;
+	dev->power.irq_safe = irq_safe;
 	spin_unlock_irq(&dev->power.lock);
 }
 EXPORT_SYMBOL_GPL(pm_runtime_irq_safe);
Index: linux/Documentation/power/runtime_pm.txt
===================================================================
--- linux.orig/Documentation/power/runtime_pm.txt
+++ linux/Documentation/power/runtime_pm.txt
@@ -434,6 +434,10 @@ drivers/base/power/runtime.c and include
       suspend and resume callbacks (but not the idle callback) to be invoked
       with interrupts disabled
 
+  void pm_runtime_irq_unsafe(struct device *dev);
+    - clear the power.irq_safe flag for the device, causing the runtime-PM
+      callbacks to be invoked with interrupts enabled
+
   void pm_runtime_mark_last_busy(struct device *dev);
     - set the power.last_busy field to the current time
 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 2/2] sh-sci / PM: Use power.irq_safe
  2011-08-20 19:31 [PATCH 0/2] sh-sci / PM: Fix problem with runtime PM callbacks run with interrupts off Rafael J. Wysocki
  2011-08-20 19:32 ` [PATCH 1/2] PM / Runtime: Introduce pm_runtime_irq_unsafe() Rafael J. Wysocki
@ 2011-08-20 19:33 ` Rafael J. Wysocki
  2011-08-21 19:09 ` [PATCH 0/2 v2] sh-sci / PM: Fix problem with runtime PM callbacks run with interrupts off Rafael J. Wysocki
  2 siblings, 0 replies; 12+ messages in thread
From: Rafael J. Wysocki @ 2011-08-20 19:33 UTC (permalink / raw)
  To: linux-sh; +Cc: Linux PM mailing list, LKML, Magnus Damm

From: Rafael J. Wysocki <rjw@sisk.pl>

Since sci_port_enable() and sci_port_disable() may be run with
interrupts off and they execute pm_runtime_get_sync() and
pm_runtime_put_sync(), respectively, the SCI device's
power.irq_safe flags has to be used to indicate that it is safe
to execute runtime PM callbacks for this device with interrupts off.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 drivers/tty/serial/sh-sci.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

Index: linux/drivers/tty/serial/sh-sci.c
===================================================================
--- linux.orig/drivers/tty/serial/sh-sci.c
+++ linux/drivers/tty/serial/sh-sci.c
@@ -1582,11 +1582,15 @@ static int sci_startup(struct uart_port
 
 	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
 
+	pm_runtime_irq_safe(port->dev);
+
 	sci_port_enable(s);
 
 	ret = sci_request_irq(s);
-	if (unlikely(ret < 0))
+	if (unlikely(ret < 0)) {
+		pm_runtime_irq_unsafe(port->dev);
 		return ret;
+	}
 
 	sci_request_dma(port);
 
@@ -1609,6 +1613,8 @@ static void sci_shutdown(struct uart_por
 	sci_free_irq(s);
 
 	sci_port_disable(s);
+
+	pm_runtime_irq_unsafe(port->dev);
 }
 
 static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [linux-pm] [PATCH 1/2] PM / Runtime: Introduce pm_runtime_irq_unsafe()
  2011-08-20 19:32 ` [PATCH 1/2] PM / Runtime: Introduce pm_runtime_irq_unsafe() Rafael J. Wysocki
@ 2011-08-21 14:55   ` Alan Stern
  2011-08-21 18:09     ` Rafael J. Wysocki
  0 siblings, 1 reply; 12+ messages in thread
From: Alan Stern @ 2011-08-21 14:55 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: linux-sh, Linux PM mailing list, LKML

On Sat, 20 Aug 2011, Rafael J. Wysocki wrote:

> From: Rafael J. Wysocki <rjw@sisk.pl>
> 
> Add a helper function allowing drivers and subsystems to clear
> the power.irq_safe device flag.

> --- linux.orig/drivers/base/power/runtime.c
> +++ linux/drivers/base/power/runtime.c
> @@ -1109,22 +1109,23 @@ void pm_runtime_no_callbacks(struct devi
>  EXPORT_SYMBOL_GPL(pm_runtime_no_callbacks);
>  
>  /**
> - * pm_runtime_irq_safe - Leave interrupts disabled during callbacks.
> + * __pm_runtime_irq_safe - Manipulate a device's power.irq_safe flag.
>   * @dev: Device to handle
> + * @irq_safe: Whether or not to leave interrupts disabled during callbacks.
>   *
> - * Set the power.irq_safe flag, which tells the PM core that the
> + * Set or unset the power.irq_safe flag, which tells the PM core that the
>   * ->runtime_suspend() and ->runtime_resume() callbacks for this device should
>   * always be invoked with the spinlock held and interrupts disabled.  It also
>   * causes the parent's usage counter to be permanently incremented, preventing
>   * the parent from runtime suspending -- otherwise an irq-safe child might have
>   * to wait for a non-irq-safe parent.
>   */
> -void pm_runtime_irq_safe(struct device *dev)
> +void __pm_runtime_irq_safe(struct device *dev, bool irq_safe)
>  {
>  	if (dev->parent)
>  		pm_runtime_get_sync(dev->parent);
>  	spin_lock_irq(&dev->power.lock);
> -	dev->power.irq_safe = 1;
> +	dev->power.irq_safe = irq_safe;
>  	spin_unlock_irq(&dev->power.lock);

It's not quite this easy.  There are two important aspects that must be
considered.

Firstly, I originally envisioned pm_runtime_irq_safe() being called
just once, before the device is enabled for runtime PM.  If you allow
the flag to be turned on and off like this, you raise the possibility
of races with runtime PM callbacks.  (That is, if a callback occurs at
about the same time as the irq_safe flag is changed, nobody can predict
whether the callback will be invoked with interrupts enabled.)  Maybe
that's something the driver needs to take care of, but it should at
least be mentioned in the documentation.

Secondly, this doesn't manage the parent's usage counter correctly.  
Do the pm_runtime_get_sync(dev->parent) at the beginning only when the
irq_safe flag was off and is being turned on.  And at the end, if the
irq_safe flag was on and is being turned off, do
pm_runtime_put_sync(dev->parent).  See pm_runtime_remove() for why this
matters.  (Also update the documentation; the change to the parent
isn't necessarily permanent any more.)

Alan Stern


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [linux-pm] [PATCH 1/2] PM / Runtime: Introduce pm_runtime_irq_unsafe()
  2011-08-21 14:55   ` [linux-pm] " Alan Stern
@ 2011-08-21 18:09     ` Rafael J. Wysocki
  0 siblings, 0 replies; 12+ messages in thread
From: Rafael J. Wysocki @ 2011-08-21 18:09 UTC (permalink / raw)
  To: Alan Stern; +Cc: linux-sh, Linux PM mailing list, LKML

On Sunday, August 21, 2011, Alan Stern wrote:
> On Sat, 20 Aug 2011, Rafael J. Wysocki wrote:
> 
> > From: Rafael J. Wysocki <rjw@sisk.pl>
> > 
> > Add a helper function allowing drivers and subsystems to clear
> > the power.irq_safe device flag.
> 
> > --- linux.orig/drivers/base/power/runtime.c
> > +++ linux/drivers/base/power/runtime.c
> > @@ -1109,22 +1109,23 @@ void pm_runtime_no_callbacks(struct devi
> >  EXPORT_SYMBOL_GPL(pm_runtime_no_callbacks);
> >  
> >  /**
> > - * pm_runtime_irq_safe - Leave interrupts disabled during callbacks.
> > + * __pm_runtime_irq_safe - Manipulate a device's power.irq_safe flag.
> >   * @dev: Device to handle
> > + * @irq_safe: Whether or not to leave interrupts disabled during callbacks.
> >   *
> > - * Set the power.irq_safe flag, which tells the PM core that the
> > + * Set or unset the power.irq_safe flag, which tells the PM core that the
> >   * ->runtime_suspend() and ->runtime_resume() callbacks for this device should
> >   * always be invoked with the spinlock held and interrupts disabled.  It also
> >   * causes the parent's usage counter to be permanently incremented, preventing
> >   * the parent from runtime suspending -- otherwise an irq-safe child might have
> >   * to wait for a non-irq-safe parent.
> >   */
> > -void pm_runtime_irq_safe(struct device *dev)
> > +void __pm_runtime_irq_safe(struct device *dev, bool irq_safe)
> >  {
> >  	if (dev->parent)
> >  		pm_runtime_get_sync(dev->parent);
> >  	spin_lock_irq(&dev->power.lock);
> > -	dev->power.irq_safe = 1;
> > +	dev->power.irq_safe = irq_safe;
> >  	spin_unlock_irq(&dev->power.lock);
> 
> It's not quite this easy.  There are two important aspects that must be
> considered.
> 
> Firstly, I originally envisioned pm_runtime_irq_safe() being called
> just once, before the device is enabled for runtime PM.  If you allow
> the flag to be turned on and off like this, you raise the possibility
> of races with runtime PM callbacks.  (That is, if a callback occurs at
> about the same time as the irq_safe flag is changed, nobody can predict
> whether the callback will be invoked with interrupts enabled.)  Maybe
> that's something the driver needs to take care of, but it should at
> least be mentioned in the documentation.

Good point.  Perhaps I should make it possible only if runtime PM is
disabled.

> Secondly, this doesn't manage the parent's usage counter correctly.

Right, I forgot about that.

> Do the pm_runtime_get_sync(dev->parent) at the beginning only when the
> irq_safe flag was off and is being turned on.  And at the end, if the
> irq_safe flag was on and is being turned off, do
> pm_runtime_put_sync(dev->parent).  See pm_runtime_remove() for why this
> matters.  (Also update the documentation; the change to the parent
> isn't necessarily permanent any more.)

I'll try to figure out an alternative approach without the $subject change
first.  If I can't, I'll revisit this idea.

Thanks,
Rafael

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 0/2 v2] sh-sci / PM: Fix problem with runtime PM callbacks run with interrupts off
  2011-08-20 19:31 [PATCH 0/2] sh-sci / PM: Fix problem with runtime PM callbacks run with interrupts off Rafael J. Wysocki
  2011-08-20 19:32 ` [PATCH 1/2] PM / Runtime: Introduce pm_runtime_irq_unsafe() Rafael J. Wysocki
  2011-08-20 19:33 ` [PATCH 2/2] sh-sci / PM: Use power.irq_safe Rafael J. Wysocki
@ 2011-08-21 19:09 ` Rafael J. Wysocki
  2011-08-21 19:10   ` [PATCH 1/2 v2] PM: Change PM subsys_data lock type into spinlock Rafael J. Wysocki
  2011-08-21 19:11   ` [PATCH 2/2 v2] sh-sci / PM: Use power.irq_safe Rafael J. Wysocki
  2 siblings, 2 replies; 12+ messages in thread
From: Rafael J. Wysocki @ 2011-08-21 19:09 UTC (permalink / raw)
  To: linux-sh; +Cc: Linux PM mailing list, LKML, Magnus Damm, Alan Stern

Hi,

> The sh-sci driver uses pm_runtime_get/put_sync() in such a way
> that they may be run with interrupts off and cause the (recently
> added) might_sleep_if() to trigger in rpm_suspend/resume().
> 
> To avoid that, it's necessary to set the SCI device's power.irq_safe
> flag to indicate that it's runtime PM callbacks may be executed with
> interrupts off safely.  However, the sh-sci driver needs to be able to
> clear that flag sometimes, so a new runtime PM helper for doing that
> is needed.

The previous version of this patchset was not very good as Alan pointed out,
so hopefully this one will be better.

[1/2] - Change PM subsys_data lock type into spinlock.
[2/2] - Make sh-sci use power.irq_safe to indicate that runtime PM callbacks
        may be run with interrupts off.

Thanks,
Rafael


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/2 v2] PM: Change PM subsys_data lock type into spinlock
  2011-08-21 19:09 ` [PATCH 0/2 v2] sh-sci / PM: Fix problem with runtime PM callbacks run with interrupts off Rafael J. Wysocki
@ 2011-08-21 19:10   ` Rafael J. Wysocki
  2011-08-22  6:18     ` [Replacement][PATCH 1/2 v2] PM: Use spinlock instead of mutex in clock management functions Rafael J. Wysocki
  2011-08-21 19:11   ` [PATCH 2/2 v2] sh-sci / PM: Use power.irq_safe Rafael J. Wysocki
  1 sibling, 1 reply; 12+ messages in thread
From: Rafael J. Wysocki @ 2011-08-21 19:10 UTC (permalink / raw)
  To: linux-sh; +Cc: Linux PM mailing list, LKML, Magnus Damm, Alan Stern

From: Rafael J. Wysocki <rjw@sisk.pl>

The lock member of struct pm_subsys_data is of type struct mutex,
which is a problem, because the suspend and resume routines
defined in drivers/base/power/clock_ops.c cannot be executed
with interrupts disabled for this reason.  Modify
struct pm_subsys_data so that its lock member is a spinlock.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 drivers/base/power/clock_ops.c |   35 +++++++++++++++++++++--------------
 drivers/base/power/common.c    |    2 +-
 include/linux/pm.h             |    2 +-
 3 files changed, 23 insertions(+), 16 deletions(-)

Index: linux/include/linux/pm.h
===================================================================
--- linux.orig/include/linux/pm.h
+++ linux/include/linux/pm.h
@@ -438,7 +438,7 @@ struct pm_domain_data {
 };
 
 struct pm_subsys_data {
-	struct mutex lock;
+	spinlock_t lock;
 	unsigned int refcount;
 #ifdef CONFIG_PM_CLK
 	struct list_head clock_list;
Index: linux/drivers/base/power/clock_ops.c
===================================================================
--- linux.orig/drivers/base/power/clock_ops.c
+++ linux/drivers/base/power/clock_ops.c
@@ -43,6 +43,7 @@ int pm_clk_add(struct device *dev, const
 {
 	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
+	unsigned long flags;
 
 	if (!psd)
 		return -EINVAL;
@@ -63,9 +64,9 @@ int pm_clk_add(struct device *dev, const
 		}
 	}
 
-	mutex_lock(&psd->lock);
+	spin_lock_irqsave(&psd->lock, flags);
 	list_add_tail(&ce->node, &psd->clock_list);
-	mutex_unlock(&psd->lock);
+	spin_unlock_irqrestore(&psd->lock, flags);
 	return 0;
 }
 
@@ -109,11 +110,12 @@ void pm_clk_remove(struct device *dev, c
 {
 	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
+	unsigned long flags;
 
 	if (!psd)
 		return;
 
-	mutex_lock(&psd->lock);
+	spin_lock_irqsave(&psd->lock, flags);
 
 	list_for_each_entry(ce, &psd->clock_list, node) {
 		if (!con_id && !ce->con_id) {
@@ -127,7 +129,7 @@ void pm_clk_remove(struct device *dev, c
 		}
 	}
 
-	mutex_unlock(&psd->lock);
+	spin_unlock_irqrestore(&psd->lock, flags);
 }
 
 /**
@@ -169,16 +171,17 @@ void pm_clk_destroy(struct device *dev)
 {
 	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce, *c;
+	unsigned long flags;
 
 	if (!psd)
 		return;
 
-	mutex_lock(&psd->lock);
+	spin_lock_irqsave(&psd->lock, flags);
 
 	list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node)
 		__pm_clk_remove(ce);
 
-	mutex_unlock(&psd->lock);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	dev_pm_put_subsys_data(dev);
 }
@@ -212,13 +215,14 @@ int pm_clk_suspend(struct device *dev)
 {
 	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
+	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
 	if (!psd)
 		return 0;
 
-	mutex_lock(&psd->lock);
+	spin_lock_irqsave(&psd->lock, flags);
 
 	list_for_each_entry_reverse(ce, &psd->clock_list, node) {
 		if (ce->status == PCE_STATUS_NONE)
@@ -230,7 +234,7 @@ int pm_clk_suspend(struct device *dev)
 		}
 	}
 
-	mutex_unlock(&psd->lock);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	return 0;
 }
@@ -243,13 +247,14 @@ int pm_clk_resume(struct device *dev)
 {
 	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
+	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
 	if (!psd)
 		return 0;
 
-	mutex_lock(&psd->lock);
+	spin_lock_irqsave(&psd->lock, flags);
 
 	list_for_each_entry(ce, &psd->clock_list, node) {
 		if (ce->status == PCE_STATUS_NONE)
@@ -261,7 +266,7 @@ int pm_clk_resume(struct device *dev)
 		}
 	}
 
-	mutex_unlock(&psd->lock);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	return 0;
 }
@@ -336,6 +341,7 @@ int pm_clk_suspend(struct device *dev)
 {
 	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
+	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
@@ -343,12 +349,12 @@ int pm_clk_suspend(struct device *dev)
 	if (!psd || !dev->driver)
 		return 0;
 
-	mutex_lock(&psd->lock);
+	spin_lock_irqsave(&psd->lock, flags);
 
 	list_for_each_entry_reverse(ce, &psd->clock_list, node)
 		clk_disable(ce->clk);
 
-	mutex_unlock(&psd->lock);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	return 0;
 }
@@ -361,6 +367,7 @@ int pm_clk_resume(struct device *dev)
 {
 	struct pm_subsys_data *psd = dev_to_psd(dev);
 	struct pm_clock_entry *ce;
+	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
@@ -368,12 +375,12 @@ int pm_clk_resume(struct device *dev)
 	if (!psd || !dev->driver)
 		return 0;
 
-	mutex_lock(&psd->lock);
+	spin_lock_irqsave(&psd->lock, flags);
 
 	list_for_each_entry(ce, &psd->clock_list, node)
 		clk_enable(ce->clk);
 
-	mutex_unlock(&psd->lock);
+	spin_unlock_irqrestore(&psd->lock, flags);
 
 	return 0;
 }
Index: linux/drivers/base/power/common.c
===================================================================
--- linux.orig/drivers/base/power/common.c
+++ linux/drivers/base/power/common.c
@@ -34,7 +34,7 @@ int dev_pm_get_subsys_data(struct device
 	if (dev->power.subsys_data) {
 		dev->power.subsys_data->refcount++;
 	} else {
-		mutex_init(&psd->lock);
+		spin_lock_init(&psd->lock);
 		psd->refcount = 1;
 		dev->power.subsys_data = psd;
 		pm_clk_init(dev);


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 2/2 v2] sh-sci / PM: Use power.irq_safe
  2011-08-21 19:09 ` [PATCH 0/2 v2] sh-sci / PM: Fix problem with runtime PM callbacks run with interrupts off Rafael J. Wysocki
  2011-08-21 19:10   ` [PATCH 1/2 v2] PM: Change PM subsys_data lock type into spinlock Rafael J. Wysocki
@ 2011-08-21 19:11   ` Rafael J. Wysocki
  2011-08-24  5:33     ` Paul Mundt
  1 sibling, 1 reply; 12+ messages in thread
From: Rafael J. Wysocki @ 2011-08-21 19:11 UTC (permalink / raw)
  To: linux-sh; +Cc: Linux PM mailing list, LKML, Magnus Damm, Alan Stern

From: Rafael J. Wysocki <rjw@sisk.pl>

Since sci_port_enable() and sci_port_disable() may be run with
interrupts off and they execute pm_runtime_get_sync() and
pm_runtime_put_sync(), respectively, the SCI device's
power.irq_safe flags has to be used to indicate that it is safe
to execute runtime PM callbacks for this device with interrupts off.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
 drivers/tty/serial/sh-sci.c |    1 +
 1 file changed, 1 insertion(+)

Index: linux/drivers/tty/serial/sh-sci.c
===================================================================
--- linux.orig/drivers/tty/serial/sh-sci.c
+++ linux/drivers/tty/serial/sh-sci.c
@@ -1913,6 +1913,7 @@ static int __devinit sci_init_single(str
 
 		port->dev = &dev->dev;
 
+		pm_runtime_irq_safe(&dev->dev);
 		pm_runtime_enable(&dev->dev);
 	}
 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [Replacement][PATCH 1/2 v2] PM: Use spinlock instead of mutex in clock management functions
  2011-08-21 19:10   ` [PATCH 1/2 v2] PM: Change PM subsys_data lock type into spinlock Rafael J. Wysocki
@ 2011-08-22  6:18     ` Rafael J. Wysocki
  0 siblings, 0 replies; 12+ messages in thread
From: Rafael J. Wysocki @ 2011-08-22  6:18 UTC (permalink / raw)
  To: linux-sh; +Cc: Linux PM mailing list, LKML, Magnus Damm, Alan Stern

From: Rafael J. Wysocki <rjw@sisk.pl>

The lock member of struct pm_clk_data is of type struct mutex,
which is a problem, because the suspend and resume routines
defined in drivers/base/power/clock_ops.c cannot be executed
with interrupts disabled for this reason.  Modify
struct pm_clk_data so that its lock member is a spinlock.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---

The previous [1/2] in this series was on top of the branch at

git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git pm-domains

but what is needed now is a version on top of the current mainline tree, which
is this one.

Thanks,
Rafael

---
 drivers/base/power/clock_ops.c |   40 ++++++++++++++++++++++------------------
 1 file changed, 22 insertions(+), 18 deletions(-)

Index: linux/drivers/base/power/clock_ops.c
===================================================================
--- linux.orig/drivers/base/power/clock_ops.c
+++ linux/drivers/base/power/clock_ops.c
@@ -19,7 +19,7 @@
 
 struct pm_clk_data {
 	struct list_head clock_list;
-	struct mutex lock;
+	spinlock_t lock;
 };
 
 enum pce_status {
@@ -73,9 +73,9 @@ int pm_clk_add(struct device *dev, const
 		}
 	}
 
-	mutex_lock(&pcd->lock);
+	spin_lock_irq(&pcd->lock);
 	list_add_tail(&ce->node, &pcd->clock_list);
-	mutex_unlock(&pcd->lock);
+	spin_unlock_irq(&pcd->lock);
 	return 0;
 }
 
@@ -83,8 +83,8 @@ int pm_clk_add(struct device *dev, const
  * __pm_clk_remove - Destroy PM clock entry.
  * @ce: PM clock entry to destroy.
  *
- * This routine must be called under the mutex protecting the PM list of clocks
- * corresponding the the @ce's device.
+ * This routine must be called under the spinlock protecting the PM list of
+ * clocks corresponding the the @ce's device.
  */
 static void __pm_clk_remove(struct pm_clock_entry *ce)
 {
@@ -123,7 +123,7 @@ void pm_clk_remove(struct device *dev, c
 	if (!pcd)
 		return;
 
-	mutex_lock(&pcd->lock);
+	spin_lock_irq(&pcd->lock);
 
 	list_for_each_entry(ce, &pcd->clock_list, node) {
 		if (!con_id && !ce->con_id) {
@@ -137,7 +137,7 @@ void pm_clk_remove(struct device *dev, c
 		}
 	}
 
-	mutex_unlock(&pcd->lock);
+	spin_unlock_irq(&pcd->lock);
 }
 
 /**
@@ -158,7 +158,7 @@ int pm_clk_init(struct device *dev)
 	}
 
 	INIT_LIST_HEAD(&pcd->clock_list);
-	mutex_init(&pcd->lock);
+	spin_lock_init(&pcd->lock);
 	dev->power.subsys_data = pcd;
 	return 0;
 }
@@ -181,12 +181,12 @@ void pm_clk_destroy(struct device *dev)
 
 	dev->power.subsys_data = NULL;
 
-	mutex_lock(&pcd->lock);
+	spin_lock_irq(&pcd->lock);
 
 	list_for_each_entry_safe_reverse(ce, c, &pcd->clock_list, node)
 		__pm_clk_remove(ce);
 
-	mutex_unlock(&pcd->lock);
+	spin_unlock_irq(&pcd->lock);
 
 	kfree(pcd);
 }
@@ -220,13 +220,14 @@ int pm_clk_suspend(struct device *dev)
 {
 	struct pm_clk_data *pcd = __to_pcd(dev);
 	struct pm_clock_entry *ce;
+	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
 	if (!pcd)
 		return 0;
 
-	mutex_lock(&pcd->lock);
+	spin_lock_irqsave(&pcd->lock, flags);
 
 	list_for_each_entry_reverse(ce, &pcd->clock_list, node) {
 		if (ce->status == PCE_STATUS_NONE)
@@ -238,7 +239,7 @@ int pm_clk_suspend(struct device *dev)
 		}
 	}
 
-	mutex_unlock(&pcd->lock);
+	spin_unlock_irqrestore(&pcd->lock, flags);
 
 	return 0;
 }
@@ -251,13 +252,14 @@ int pm_clk_resume(struct device *dev)
 {
 	struct pm_clk_data *pcd = __to_pcd(dev);
 	struct pm_clock_entry *ce;
+	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
 	if (!pcd)
 		return 0;
 
-	mutex_lock(&pcd->lock);
+	spin_lock_irqsave(&pcd->lock, flags);
 
 	list_for_each_entry(ce, &pcd->clock_list, node) {
 		if (ce->status == PCE_STATUS_NONE)
@@ -269,7 +271,7 @@ int pm_clk_resume(struct device *dev)
 		}
 	}
 
-	mutex_unlock(&pcd->lock);
+	spin_unlock_irqrestore(&pcd->lock, flags);
 
 	return 0;
 }
@@ -344,6 +346,7 @@ int pm_clk_suspend(struct device *dev)
 {
 	struct pm_clk_data *pcd = __to_pcd(dev);
 	struct pm_clock_entry *ce;
+	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
@@ -351,12 +354,12 @@ int pm_clk_suspend(struct device *dev)
 	if (!pcd || !dev->driver)
 		return 0;
 
-	mutex_lock(&pcd->lock);
+	spin_lock_irqsave(&pcd->lock, flags);
 
 	list_for_each_entry_reverse(ce, &pcd->clock_list, node)
 		clk_disable(ce->clk);
 
-	mutex_unlock(&pcd->lock);
+	spin_unlock_irqrestore(&pcd->lock, flags);
 
 	return 0;
 }
@@ -369,6 +372,7 @@ int pm_clk_resume(struct device *dev)
 {
 	struct pm_clk_data *pcd = __to_pcd(dev);
 	struct pm_clock_entry *ce;
+	unsigned long flags;
 
 	dev_dbg(dev, "%s()\n", __func__);
 
@@ -376,12 +380,12 @@ int pm_clk_resume(struct device *dev)
 	if (!pcd || !dev->driver)
 		return 0;
 
-	mutex_lock(&pcd->lock);
+	spin_lock_irqsave(&pcd->lock, flags);
 
 	list_for_each_entry(ce, &pcd->clock_list, node)
 		clk_enable(ce->clk);
 
-	mutex_unlock(&pcd->lock);
+	spin_unlock_irqrestore(&pcd->lock, flags);
 
 	return 0;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2 v2] sh-sci / PM: Use power.irq_safe
  2011-08-21 19:11   ` [PATCH 2/2 v2] sh-sci / PM: Use power.irq_safe Rafael J. Wysocki
@ 2011-08-24  5:33     ` Paul Mundt
  2011-08-24 20:52       ` Rafael J. Wysocki
  0 siblings, 1 reply; 12+ messages in thread
From: Paul Mundt @ 2011-08-24  5:33 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: linux-sh, Linux PM mailing list, LKML, Magnus Damm, Alan Stern

On Sun, Aug 21, 2011 at 09:11:44PM +0200, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rjw@sisk.pl>
> 
> Since sci_port_enable() and sci_port_disable() may be run with
> interrupts off and they execute pm_runtime_get_sync() and
> pm_runtime_put_sync(), respectively, the SCI device's
> power.irq_safe flags has to be used to indicate that it is safe
> to execute runtime PM callbacks for this device with interrupts off.
> 
> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>

Not sure how you want this one handled. Did you simply want to roll this
in with your other patch with my Acked-by, or should I be taking this
through my tree already regardless of the 1/2 patch?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2 v2] sh-sci / PM: Use power.irq_safe
  2011-08-24  5:33     ` Paul Mundt
@ 2011-08-24 20:52       ` Rafael J. Wysocki
  2011-08-25  1:33         ` Paul Mundt
  0 siblings, 1 reply; 12+ messages in thread
From: Rafael J. Wysocki @ 2011-08-24 20:52 UTC (permalink / raw)
  To: Paul Mundt; +Cc: linux-sh, Linux PM mailing list, LKML, Magnus Damm, Alan Stern

On Wednesday, August 24, 2011, Paul Mundt wrote:
> On Sun, Aug 21, 2011 at 09:11:44PM +0200, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rjw@sisk.pl>
> > 
> > Since sci_port_enable() and sci_port_disable() may be run with
> > interrupts off and they execute pm_runtime_get_sync() and
> > pm_runtime_put_sync(), respectively, the SCI device's
> > power.irq_safe flags has to be used to indicate that it is safe
> > to execute runtime PM callbacks for this device with interrupts off.
> > 
> > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> 
> Not sure how you want this one handled. Did you simply want to roll this
> in with your other patch with my Acked-by, or should I be taking this
> through my tree already regardless of the 1/2 patch?

I'd prefer to push it through my tree, if you don't mind.  Magnus has
already acked it for me, hopefully that's OK?

Rafael

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/2 v2] sh-sci / PM: Use power.irq_safe
  2011-08-24 20:52       ` Rafael J. Wysocki
@ 2011-08-25  1:33         ` Paul Mundt
  0 siblings, 0 replies; 12+ messages in thread
From: Paul Mundt @ 2011-08-25  1:33 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: linux-sh, Linux PM mailing list, LKML, Magnus Damm, Alan Stern

On Wed, Aug 24, 2011 at 10:52:24PM +0200, Rafael J. Wysocki wrote:
> On Wednesday, August 24, 2011, Paul Mundt wrote:
> > On Sun, Aug 21, 2011 at 09:11:44PM +0200, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rjw@sisk.pl>
> > > 
> > > Since sci_port_enable() and sci_port_disable() may be run with
> > > interrupts off and they execute pm_runtime_get_sync() and
> > > pm_runtime_put_sync(), respectively, the SCI device's
> > > power.irq_safe flags has to be used to indicate that it is safe
> > > to execute runtime PM callbacks for this device with interrupts off.
> > > 
> > > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> > 
> > Not sure how you want this one handled. Did you simply want to roll this
> > in with your other patch with my Acked-by, or should I be taking this
> > through my tree already regardless of the 1/2 patch?
> 
> I'd prefer to push it through my tree, if you don't mind.  Magnus has
> already acked it for me, hopefully that's OK?
> 
Sure, sounds fine to me. I'll just ignore it then.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2011-08-25  1:34 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-20 19:31 [PATCH 0/2] sh-sci / PM: Fix problem with runtime PM callbacks run with interrupts off Rafael J. Wysocki
2011-08-20 19:32 ` [PATCH 1/2] PM / Runtime: Introduce pm_runtime_irq_unsafe() Rafael J. Wysocki
2011-08-21 14:55   ` [linux-pm] " Alan Stern
2011-08-21 18:09     ` Rafael J. Wysocki
2011-08-20 19:33 ` [PATCH 2/2] sh-sci / PM: Use power.irq_safe Rafael J. Wysocki
2011-08-21 19:09 ` [PATCH 0/2 v2] sh-sci / PM: Fix problem with runtime PM callbacks run with interrupts off Rafael J. Wysocki
2011-08-21 19:10   ` [PATCH 1/2 v2] PM: Change PM subsys_data lock type into spinlock Rafael J. Wysocki
2011-08-22  6:18     ` [Replacement][PATCH 1/2 v2] PM: Use spinlock instead of mutex in clock management functions Rafael J. Wysocki
2011-08-21 19:11   ` [PATCH 2/2 v2] sh-sci / PM: Use power.irq_safe Rafael J. Wysocki
2011-08-24  5:33     ` Paul Mundt
2011-08-24 20:52       ` Rafael J. Wysocki
2011-08-25  1:33         ` Paul Mundt

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).