diff options
| author | Praveen Talari <praveen.talari@oss.qualcomm.com> | 2026-07-15 09:55:14 +0530 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-07-17 13:02:19 +0200 |
| commit | dbe2afb952bdb782450d8f678adeb502791e7edd (patch) | |
| tree | 4eec3bb8c6f059c3dd195bb6448e652a7f3c9f6d /drivers/tty/serial | |
| parent | 6e5bd7cc3a2f304a66d294011647d82074421979 (diff) | |
| download | linux-next-dbe2afb952bdb782450d8f678adeb502791e7edd.tar.gz linux-next-dbe2afb952bdb782450d8f678adeb502791e7edd.zip | |
serial: qcom_geni: Add shutdown callback to quiesce hardware on reboot
During system reboot, an active UART DMA transfer can leave the GENI
Serial Engine in an indeterminate state. On VM-based platforms, if a
DMA transfer is in progress when the VM is shut down, the SMMU can
raise context faults as the DMA engine continues to access IOVAs that
have already been invalidated during VM teardown.
Add a shutdown callback to stop TX and RX and bring the hardware to
idle before the system resets, preventing both hardware state corruption
on reboot and SMMU faults during VM shutdown. The port lock is not taken
here since shutdown runs from process context with the device already
quiesced from the UART core's perspective; instead, the runtime PM status
is checked so that TX/RX are only stopped while clocks and resources are
still active, avoiding any register access once the device is runtime
suspended.
Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com>
Link: https://patch.msgid.link/20260715-add_shutdown_and_panic_notifier_serial-v1-1-23e3787c7109@oss.qualcomm.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial')
| -rw-r--r-- | drivers/tty/serial/qcom_geni_serial.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 751738f848ad..04e1227390dd 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -2112,6 +2112,18 @@ static const struct dev_pm_ops qcom_geni_serial_pm_ops = { SYSTEM_SLEEP_PM_OPS(qcom_geni_serial_suspend, qcom_geni_serial_resume) }; +static void qcom_geni_serial_sys_shutdown(struct platform_device *pdev) +{ + struct qcom_geni_serial_port *port = platform_get_drvdata(pdev); + struct uart_port *uport = &port->uport; + + if (pm_runtime_status_suspended(uport->dev)) + return; + + qcom_geni_serial_stop_tx(uport); + qcom_geni_serial_stop_rx(uport); +} + static const struct of_device_id qcom_geni_serial_match_table[] = { #if IS_ENABLED(CONFIG_SERIAL_QCOM_GENI_CONSOLE) { @@ -2138,6 +2150,7 @@ MODULE_DEVICE_TABLE(of, qcom_geni_serial_match_table); static struct platform_driver qcom_geni_serial_platform_driver = { .remove = qcom_geni_serial_remove, .probe = qcom_geni_serial_probe, + .shutdown = qcom_geni_serial_sys_shutdown, .driver = { .name = "qcom_geni_serial", .of_match_table = qcom_geni_serial_match_table, |
