Skip to content

Commit 92fd91d

Browse files
VCASTMADESTM
authored andcommitted
serial: stm32: do not call pm_runtime before startup and after shutdown
The driver failed to call pm_runtime_resume before the shutdown routine because tty_port is uninitialized when shutdown is called. For example the bit USART_CR1_RXNEIE is correctly set during the runtime_suspend routine but if we close the port while the device is suspended: the runtime_resume returns immediately due to the !tty_port_initialized condition and the bit USART_CR1_RXNEIE is never cleared. That will cause issues at the next startup. To solve this, the !tty_port_initialized condition is removed and replaced by a boolean "started", which is active when the runtime routines can be done after port startup is complete. - After a probe the device is considered suspended - The startup calls a pm_get but the runtime_resume routine returns immediately. - The startup calls a pm_put and the runtime_suspend routine is executed normally as the driver has completed its startup function. - The shutdown calls a pm_get and the runtime_resume routine is executed normally. - The shutdown calls a pm_put but the runtime_suspend routine returns immediately. - The remove forces the device to suspended state. Signed-off-by: Valentin Caron <valentin.caron@foss.st.com> Change-Id: Ibf8210021aebc3a7bd144c06c080d378b8928b66 Reviewed-on: https://gerrit.st.com/c/mpu/oe/st/linux-stm32/+/563753 ACI: CITOOLS <MDG-smet-aci-reviews@list.st.com> Reviewed-by: Amelie DELAUNAY <amelie.delaunay@foss.st.com> Domain-Review: Amelie DELAUNAY <amelie.delaunay@foss.st.com> ACI: CIBUILD <MDG-smet-aci-builds@list.st.com>
1 parent e31e8b8 commit 92fd91d

2 files changed

Lines changed: 10 additions & 8 deletions

File tree

drivers/tty/serial/stm32-usart.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,7 @@ static int stm32_usart_startup(struct uart_port *port)
13691369
u32 val;
13701370
int ret;
13711371

1372-
pm_runtime_get(port->dev);
1372+
pm_runtime_get_sync(port->dev);
13731373

13741374
ret = request_irq(port->irq, stm32_usart_interrupt, 0, name, port);
13751375
if (ret)
@@ -1398,9 +1398,11 @@ static int stm32_usart_startup(struct uart_port *port)
13981398
val = stm32_port->cr1_irq | USART_CR1_RE | BIT(cfg->uart_enable_bit);
13991399
stm32_usart_set_bits(port, ofs->cr1, val);
14001400

1401+
stm32_port->started = true;
1402+
14011403
out:
14021404
pm_runtime_mark_last_busy(port->dev);
1403-
pm_runtime_put_autosuspend(port->dev);
1405+
pm_runtime_put_sync_autosuspend(port->dev);
14041406

14051407
return ret;
14061408
}
@@ -1413,7 +1415,9 @@ static void stm32_usart_shutdown(struct uart_port *port)
14131415
u32 val, isr;
14141416
int ret;
14151417

1416-
pm_runtime_get(port->dev);
1418+
pm_runtime_get_sync(port->dev);
1419+
1420+
stm32_port->started = false;
14171421

14181422
ret = readl_relaxed_poll_timeout(port->membase + ofs->isr,
14191423
isr, (isr & USART_SR_TC),
@@ -1453,8 +1457,7 @@ static void stm32_usart_shutdown(struct uart_port *port)
14531457

14541458
stm32_usart_clr_bits(port, ofs->cr1, val);
14551459

1456-
pm_runtime_mark_last_busy(port->dev);
1457-
pm_runtime_put_autosuspend(port->dev);
1460+
pm_runtime_put_sync_suspend(port->dev);
14581461

14591462
free_irq(port->irq, port);
14601463
}
@@ -2198,7 +2201,6 @@ static int stm32_usart_serial_probe(struct platform_device *pdev)
21982201
if (ret)
21992202
goto err_rtor;
22002203

2201-
pm_runtime_set_active(&pdev->dev);
22022204
pm_runtime_use_autosuspend(&pdev->dev);
22032205
pm_runtime_set_autosuspend_delay(&pdev->dev, STM32_USART_AUTOSUSPEND_DELAY_MS);
22042206
pm_runtime_enable(&pdev->dev);
@@ -2246,7 +2248,6 @@ static int stm32_usart_serial_remove(struct platform_device *pdev)
22462248

22472249
pm_runtime_disable(&pdev->dev);
22482250
pm_runtime_set_suspended(&pdev->dev);
2249-
pm_runtime_put_noidle(&pdev->dev);
22502251

22512252
stm32_usart_clr_bits(port, ofs->cr1, USART_CR1_PEIE);
22522253

@@ -2440,7 +2441,7 @@ static int __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port,
24402441
unsigned int size = 0;
24412442
unsigned long flags;
24422443

2443-
if (!device_can_wakeup(port->dev) || !tty_port_initialized(tport))
2444+
if (!device_can_wakeup(port->dev) || !stm32_port->started)
24442445
return 0;
24452446

24462447
/*

drivers/tty/serial/stm32-usart.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ struct stm32_port {
240240
unsigned int tx_dma_bytes;
241241
bool tx_dma_busy; /* dma tx transaction in progress */
242242
bool rx_dma_busy; /* dma rx transaction in progress */
243+
bool started; /* to enable runtime_resume/suspend between startup and shutdown */
243244
bool throttled; /* port throttled */
244245
bool hw_flow_control;
245246
bool swap; /* swap RX & TX pins */

0 commit comments

Comments
 (0)