| From b503e9756dc79ffaf2b3160b79c1bf2aed842547 Mon Sep 17 00:00:00 2001 |
| From: Dan Williams <dan.j.williams@intel.com> |
| Date: Fri, 6 Apr 2012 11:49:50 -0700 |
| Subject: serial/8250_pci: add a "force background timer" flag and use it for |
| the "kt" serial port |
| |
| Workaround dropped notifications in the iir register. Register reads |
| coincident with new interrupt notifications sometimes result in this |
| device clearing the interrupt event without reporting it in the read |
| data. |
| |
| The serial core already has a heuristic for determining when a device |
| has an untrustworthy iir register. In this case when we apriori know |
| that the iir is faulty use a flag (UPF_BUG_THRE) to bypass the test and |
| force usage of the background timer. |
| |
| [stable: 3.3.x] |
| Acked-by: Alan Cox <alan@linux.intel.com> |
| Cc: stable <stable@vger.kernel.org> |
| Reported-by: Nhan H Mai <nhan.h.mai@intel.com> |
| Reported-by: Sudhakar Mamillapalli <sudhakar@fb.com> |
| Tested-by: Nhan H Mai <nhan.h.mai@intel.com> |
| Tested-by: Sudhakar Mamillapalli <sudhakar@fb.com> |
| Signed-off-by: Dan Williams <dan.j.williams@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| (cherry picked from commit bc02d15a3452fdf9276e8fb89c5e504a88df888a) |
| |
| Signed-off-by: Simon Horman <horms@verge.net.au> |
| --- |
| drivers/tty/serial/8250/8250.c | 8 +++++--- |
| drivers/tty/serial/8250/8250_pci.c | 17 ++++++++++++++++- |
| include/linux/serial_core.h | 1 + |
| 3 files changed, 22 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/tty/serial/8250/8250.c |
| +++ b/drivers/tty/serial/8250/8250.c |
| @@ -2035,10 +2035,12 @@ static int serial8250_startup(struct uar |
| spin_unlock_irqrestore(&port->lock, flags); |
| |
| /* |
| - * If the interrupt is not reasserted, setup a timer to |
| - * kick the UART on a regular basis. |
| + * If the interrupt is not reasserted, or we otherwise |
| + * don't trust the iir, setup a timer to kick the UART |
| + * on a regular basis. |
| */ |
| - if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) { |
| + if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) || |
| + up->port.flags & UPF_BUG_THRE) { |
| up->bugs |= UART_BUG_THRE; |
| pr_debug("ttyS%d - using backup timer\n", |
| serial_index(port)); |
| --- a/drivers/tty/serial/8250/8250_pci.c |
| +++ b/drivers/tty/serial/8250/8250_pci.c |
| @@ -994,6 +994,14 @@ static int skip_tx_en_setup(struct seria |
| return pci_default_setup(priv, board, port, idx); |
| } |
| |
| +static int kt_serial_setup(struct serial_private *priv, |
| + const struct pciserial_board *board, |
| + struct uart_port *port, int idx) |
| +{ |
| + port->flags |= UPF_BUG_THRE; |
| + return skip_tx_en_setup(priv, board, port, idx); |
| +} |
| + |
| static int pci_eg20t_init(struct pci_dev *dev) |
| { |
| #if defined(CONFIG_SERIAL_PCH_UART) || defined(CONFIG_SERIAL_PCH_UART_MODULE) |
| @@ -1012,7 +1020,6 @@ pci_xr17c154_setup(struct serial_private |
| return pci_default_setup(priv, board, port, idx); |
| } |
| |
| -/* This should be in linux/pci_ids.h */ |
| #define PCI_VENDOR_ID_SBSMODULARIO 0x124B |
| #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B |
| #define PCI_DEVICE_ID_OCTPRO 0x0001 |
| @@ -1040,6 +1047,7 @@ pci_xr17c154_setup(struct serial_private |
| #define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538 |
| #define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6 |
| #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001 |
| +#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d |
| |
| /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ |
| #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 |
| @@ -1124,6 +1132,13 @@ static struct pci_serial_quirk pci_seria |
| .subdevice = PCI_ANY_ID, |
| .setup = ce4100_serial_setup, |
| }, |
| + { |
| + .vendor = PCI_VENDOR_ID_INTEL, |
| + .device = PCI_DEVICE_ID_INTEL_PATSBURG_KT, |
| + .subvendor = PCI_ANY_ID, |
| + .subdevice = PCI_ANY_ID, |
| + .setup = kt_serial_setup, |
| + }, |
| /* |
| * ITE |
| */ |
| --- a/include/linux/serial_core.h |
| +++ b/include/linux/serial_core.h |
| @@ -351,6 +351,7 @@ struct uart_port { |
| #define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) |
| #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) |
| #define UPF_EXAR_EFR ((__force upf_t) (1 << 25)) |
| +#define UPF_BUG_THRE ((__force upf_t) (1 << 26)) |
| /* The exact UART type is known and should not be probed. */ |
| #define UPF_FIXED_TYPE ((__force upf_t) (1 << 27)) |
| #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28)) |