summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/serial/8250/8250_exar.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index 3a39368e6e47..357e20a6566f 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -19,6 +19,7 @@
#include <linux/string.h>
#include <linux/tty.h>
#include <linux/8250_pci.h>
+#include <linux/delay.h>
#include <asm/byteorder.h>
@@ -515,6 +516,27 @@ static irqreturn_t exar_misc_handler(int irq, void *data)
return IRQ_HANDLED;
}
+static void
+exar_shutdown(struct uart_port *port)
+{
+ unsigned char lsr;
+ bool tx_complete = 0;
+ struct uart_8250_port *up = up_to_u8250p(port);
+ struct circ_buf *xmit = &port->state->xmit;
+ int i = 0;
+
+ do {
+ lsr = serial_in(up, UART_LSR);
+ if (lsr & (UART_LSR_TEMT | UART_LSR_THRE))
+ tx_complete = 1;
+ else
+ tx_complete = 0;
+ msleep(1);
+ } while (!uart_circ_empty(xmit) && !tx_complete && i++ < 1000);
+
+ serial8250_do_shutdown(port);
+}
+
static int
exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
{
@@ -555,6 +577,7 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
uart.port.flags = UPF_SHARE_IRQ | UPF_EXAR_EFR | UPF_FIXED_TYPE | UPF_FIXED_PORT;
uart.port.irq = pci_irq_vector(pcidev, 0);
uart.port.dev = &pcidev->dev;
+ uart.port.shutdown = exar_shutdown;
rc = devm_request_irq(&pcidev->dev, uart.port.irq, exar_misc_handler,
IRQF_SHARED, "exar_uart", priv);