summaryrefslogtreecommitdiff
path: root/drivers/tty/serial
diff options
context:
space:
mode:
authorPraveen Talari <praveen.talari@oss.qualcomm.com>2026-07-15 09:55:15 +0530
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-17 13:02:19 +0200
commit5d51a3958ae03e2eda5db9e32b4b224d17faf7d2 (patch)
tree987c29b09b2c6af47c20ddec002cb6d4fc312c07 /drivers/tty/serial
parentdbe2afb952bdb782450d8f678adeb502791e7edd (diff)
downloadlinux-next-5d51a3958ae03e2eda5db9e32b4b224d17faf7d2.tar.gz
linux-next-5d51a3958ae03e2eda5db9e32b4b224d17faf7d2.zip
serial: qcom_geni: Add panic notifier to stop UART on panic
When a VM crashes with an active UART DMA transfer in progress, the SMMU raises context faults as the DMA engine continues to access IOVAs that are invalidated when the VM's memory context is torn down. These faults can affect other VMs sharing the same SMMU instance and obscure the root cause of the crash. Additionally, a stuck TX transfer on the panic console UART can cause the panic handler to stall, dropping the panic output. Register a panic notifier to stop TX and RX. The notifier does not take the port lock, since panic can be entered with the lock already held by the interrupted context, and there is no safe way to detect that here; instead, the device's runtime PM status is checked first so that TX/RX are only stopped while the hardware is still clocked and accessible, and the register accesses are skipped entirely 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-2-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.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 04e1227390dd..67b14fda4ff9 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -18,6 +18,7 @@
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/panic_notifier.h>
#include <linux/pm_domain.h>
#include <linux/pm_opp.h>
#include <linux/platform_device.h>
@@ -156,6 +157,7 @@ struct qcom_geni_serial_port {
struct qcom_geni_private_data private_data;
const struct qcom_geni_device_data *dev_data;
struct dev_pm_domain_list *pd_list;
+ struct notifier_block panic_nb;
};
static const struct uart_ops qcom_geni_console_pops;
@@ -1824,6 +1826,22 @@ static const struct uart_ops qcom_geni_uart_pops = {
.pm = qcom_geni_serial_pm,
};
+static int qcom_geni_serial_panic_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct qcom_geni_serial_port *port =
+ container_of(nb, struct qcom_geni_serial_port, panic_nb);
+ struct uart_port *uport = &port->uport;
+
+ if (pm_runtime_status_suspended(uport->dev))
+ return NOTIFY_OK;
+
+ qcom_geni_serial_stop_tx(uport);
+ qcom_geni_serial_stop_rx(uport);
+
+ return NOTIFY_OK;
+}
+
static int qcom_geni_serial_probe(struct platform_device *pdev)
{
int ret = 0;
@@ -1959,6 +1977,9 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
if (ret)
goto error;
+ port->panic_nb.notifier_call = qcom_geni_serial_panic_notifier;
+ atomic_notifier_chain_register(&panic_notifier_list, &port->panic_nb);
+
return 0;
error:
@@ -1977,6 +1998,8 @@ static void qcom_geni_serial_remove(struct platform_device *pdev)
struct uart_port *uport = &port->uport;
struct uart_driver *drv = port->private_data.drv;
+ atomic_notifier_chain_unregister(&panic_notifier_list, &port->panic_nb);
+
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
ida_free(&port_ida, uport->line);