Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 47b1747f authored by Robert Middleton's avatar Robert Middleton Committed by Greg Kroah-Hartman
Browse files

serial: 8250_exar: Clear buffer before shutdown



When closing and shutting down the exar serial port, if the chip
has not finished sending all of the data in its buffer, the
remaining bytes will be lost.  Hold off on the shutdown until the
bytes have all been sent.

Signed-off-by: default avatarRobert Middleton <robert.middleton@rm5248.com>
Link: https://lore.kernel.org/r/20190801145640.26080-1-robert.middleton@rm5248.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent b2b4b8ed
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -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);