Commit 048be431 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Paul Mundt

sh-sci / PM: Avoid deadlocking runtime PM

The runtime PM of sh-sci devices is enabled when sci_probe() returns,
so the pm_runtime_put_sync() executed by driver_probe_device()
attempts to suspend the device.  Then, in some situations, a
diagnostic message is printed to the console by one of the runtime
suspend routines handling the sh-sci device, which causes synchronous
runtime resume to be started from the device's own runtime suspend
callback.  This causes rpm_resume() to be run eventually, which sees
the RPM_SUSPENDING status set by rpm_suspend() and waits for it to
change.  However, the device's runtime PM status cannot change at
that point, because the routine that has set it waits for the
rpm_suspend() to return.  A deadlock occurs as a result.

To avoid that make sci_init_single() increment the device's
runtime PM usage counter, so that it cannot be suspended by
driver_probe_device().  That counter has to be decremented
eventually, so make sci_startup() do that before starting to
actually use the device and make sci_shutdown() increment it
again before returning to balance the incrementation carried out by
sci_startup().
Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Tested-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 948c46a1
...@@ -1710,6 +1710,8 @@ static int sci_startup(struct uart_port *port) ...@@ -1710,6 +1710,8 @@ static int sci_startup(struct uart_port *port)
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
pm_runtime_put_noidle(port->dev);
sci_port_enable(s); sci_port_enable(s);
ret = sci_request_irq(s); ret = sci_request_irq(s);
...@@ -1737,6 +1739,8 @@ static void sci_shutdown(struct uart_port *port) ...@@ -1737,6 +1739,8 @@ static void sci_shutdown(struct uart_port *port)
sci_free_irq(s); sci_free_irq(s);
sci_port_disable(s); sci_port_disable(s);
pm_runtime_get_noresume(port->dev);
} }
static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
...@@ -2075,6 +2079,7 @@ static int __devinit sci_init_single(struct platform_device *dev, ...@@ -2075,6 +2079,7 @@ static int __devinit sci_init_single(struct platform_device *dev,
sci_init_gpios(sci_port); sci_init_gpios(sci_port);
pm_runtime_irq_safe(&dev->dev); pm_runtime_irq_safe(&dev->dev);
pm_runtime_get_noresume(&dev->dev);
pm_runtime_enable(&dev->dev); pm_runtime_enable(&dev->dev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment