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: Rafael J. Wysocki <rjw@sisk.pl> Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
Родитель
948c46a195
Коммит
048be431e4
|
@ -1710,6 +1710,8 @@ static int sci_startup(struct uart_port *port)
|
|||
|
||||
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
|
||||
|
||||
pm_runtime_put_noidle(port->dev);
|
||||
|
||||
sci_port_enable(s);
|
||||
|
||||
ret = sci_request_irq(s);
|
||||
|
@ -1737,6 +1739,8 @@ static void sci_shutdown(struct uart_port *port)
|
|||
sci_free_irq(s);
|
||||
|
||||
sci_port_disable(s);
|
||||
|
||||
pm_runtime_get_noresume(port->dev);
|
||||
}
|
||||
|
||||
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,
|
|||
sci_init_gpios(sci_port);
|
||||
|
||||
pm_runtime_irq_safe(&dev->dev);
|
||||
pm_runtime_get_noresume(&dev->dev);
|
||||
pm_runtime_enable(&dev->dev);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче