Commit 72169e42 authored by Aaron Sierra's avatar Aaron Sierra Committed by Greg Kroah-Hartman

serial: 8250_exar: Absorb remaining 8250_port INT0 support

Move INT0 clearing out of common, per-port serial8250_do_startup()
into PCI device probe/resume.

As described in commit 2c0ac5b4 ("serial: exar: Fix stuck MSIs"),
the purpose of clearing INT0 is to prevent the PCI interrupt line from
becoming stuck asserted, "which is fatal with edge-triggered MSIs".

Like the clearing via interrupt handler that moved from common code in
commit c7e1b405 ("tty: serial: exar: Relocate sleep wake-up
handling"), this clearing at startup can be better handled at the PCI
device level.

Cc: Jan Kiszka <jan.kiszka@siemens.com>
Cc: Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>
Signed-off-by: default avatarAaron Sierra <asierra@xes-inc.com>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20190801185956.3222-1-asierra@xes-inc.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7027e62a
......@@ -493,6 +493,16 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev)
port->port.private_data = NULL;
}
static inline void exar_misc_clear(struct exar8250 *priv)
{
/* Clear all PCI interrupts by reading INT0. No effect on IIR */
readb(priv->virt + UART_EXAR_INT0);
/* Clear INT0 for Expansion Interface slave ports, too */
if (priv->board->num_ports > 8)
readb(priv->virt + 0x2000 + UART_EXAR_INT0);
}
/*
* These Exar UARTs have an extra interrupt indicator that could fire for a
* few interrupts that are not presented/cleared through IIR. One of which is
......@@ -504,14 +514,7 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev)
*/
static irqreturn_t exar_misc_handler(int irq, void *data)
{
struct exar8250 *priv = data;
/* Clear all PCI interrupts by reading INT0. No effect on IIR */
readb(priv->virt + UART_EXAR_INT0);
/* Clear INT0 for Expansion Interface slave ports, too */
if (priv->board->num_ports > 8)
readb(priv->virt + 0x2000 + UART_EXAR_INT0);
exar_misc_clear(data);
return IRQ_HANDLED;
}
......@@ -584,6 +587,9 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
if (rc)
return rc;
/* Clear interrupts */
exar_misc_clear(priv);
for (i = 0; i < nr_ports && i < maxnr; i++) {
rc = board->setup(priv, pcidev, &uart, i);
if (rc) {
......@@ -642,6 +648,8 @@ static int __maybe_unused exar_resume(struct device *dev)
struct exar8250 *priv = dev_get_drvdata(dev);
unsigned int i;
exar_misc_clear(priv);
for (i = 0; i < priv->nr; i++)
if (priv->line[i] >= 0)
serial8250_resume_port(priv->line[i]);
......
......@@ -40,11 +40,6 @@
#include "8250.h"
/*
* These are definitions for the Exar XR17V35X and XR17(C|D)15X
*/
#define UART_EXAR_INT0 0x80
/* Nuvoton NPCM timeout register */
#define UART_NPCM_TOR 7
#define UART_NPCM_TOIE BIT(7) /* Timeout Interrupt Enable */
......@@ -2138,8 +2133,6 @@ int serial8250_do_startup(struct uart_port *port)
serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
serial_port_in(port, UART_EXAR_INT0);
/*
* At this point, there's no way the LSR could still be 0xff;
......@@ -2297,8 +2290,6 @@ int serial8250_do_startup(struct uart_port *port)
serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
serial_port_in(port, UART_EXAR_INT0);
up->lsr_saved_flags = 0;
up->msr_saved_flags = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment