Commit 65ecc9c0 authored by Sean Young's avatar Sean Young Committed by Greg Kroah-Hartman

8250: blacklist Winbond CIR port

The legacy serial driver will detect the Winbond CIR device as a serial
port, since it looks exactly like a serial port unless you know what
it is from the PNP ID.

Here we track this port as a special PORT_8250_CIR type, preventing the
legacy serial driver from probing it.
Signed-off-by: default avatarSean Young <sean@mess.org>
Acked-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 835d844d
...@@ -290,6 +290,9 @@ static const struct serial8250_config uart_config[] = { ...@@ -290,6 +290,9 @@ static const struct serial8250_config uart_config[] = {
UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
.flags = UART_CAP_FIFO, .flags = UART_CAP_FIFO,
}, },
[PORT_8250_CIR] = {
.name = "CIR port"
}
}; };
/* Uart divisor latch read */ /* Uart divisor latch read */
...@@ -1900,6 +1903,9 @@ static int serial8250_startup(struct uart_port *port) ...@@ -1900,6 +1903,9 @@ static int serial8250_startup(struct uart_port *port)
unsigned char lsr, iir; unsigned char lsr, iir;
int retval; int retval;
if (port->type == PORT_8250_CIR)
return -ENODEV;
port->fifosize = uart_config[up->port.type].fifo_size; port->fifosize = uart_config[up->port.type].fifo_size;
up->tx_loadsz = uart_config[up->port.type].tx_loadsz; up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
up->capabilities = uart_config[up->port.type].flags; up->capabilities = uart_config[up->port.type].flags;
...@@ -2557,7 +2563,10 @@ static int serial8250_request_port(struct uart_port *port) ...@@ -2557,7 +2563,10 @@ static int serial8250_request_port(struct uart_port *port)
{ {
struct uart_8250_port *up = struct uart_8250_port *up =
container_of(port, struct uart_8250_port, port); container_of(port, struct uart_8250_port, port);
int ret = 0; int ret;
if (port->type == PORT_8250_CIR)
return -ENODEV;
ret = serial8250_request_std_resource(up); ret = serial8250_request_std_resource(up);
if (ret == 0 && port->type == PORT_RSA) { if (ret == 0 && port->type == PORT_RSA) {
...@@ -2576,6 +2585,9 @@ static void serial8250_config_port(struct uart_port *port, int flags) ...@@ -2576,6 +2585,9 @@ static void serial8250_config_port(struct uart_port *port, int flags)
int probeflags = PROBE_ANY; int probeflags = PROBE_ANY;
int ret; int ret;
if (port->type == PORT_8250_CIR)
return;
/* /*
* Find the region that we can probe for. This in turn * Find the region that we can probe for. This in turn
* tells us whether we can probe for the type of port. * tells us whether we can probe for the type of port.
...@@ -3147,7 +3159,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up) ...@@ -3147,7 +3159,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
mutex_lock(&serial_mutex); mutex_lock(&serial_mutex);
uart = serial8250_find_match_or_unused(&up->port); uart = serial8250_find_match_or_unused(&up->port);
if (uart) { if (uart && uart->port.type != PORT_8250_CIR) {
if (uart->port.dev) if (uart->port.dev)
uart_remove_one_port(&serial8250_reg, &uart->port); uart_remove_one_port(&serial8250_reg, &uart->port);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "8250.h" #include "8250.h"
#define UNKNOWN_DEV 0x3000 #define UNKNOWN_DEV 0x3000
#define CIR_PORT 0x0800
static const struct pnp_device_id pnp_dev_table[] = { static const struct pnp_device_id pnp_dev_table[] = {
/* Archtek America Corp. */ /* Archtek America Corp. */
...@@ -362,6 +362,9 @@ static const struct pnp_device_id pnp_dev_table[] = { ...@@ -362,6 +362,9 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "PNPCXXX", UNKNOWN_DEV }, { "PNPCXXX", UNKNOWN_DEV },
/* More unknown PnP modems */ /* More unknown PnP modems */
{ "PNPDXXX", UNKNOWN_DEV }, { "PNPDXXX", UNKNOWN_DEV },
/* Winbond CIR port, should not be probed. We should keep track
of it to prevent the legacy serial driver from probing it */
{ "WEC1022", CIR_PORT },
{ "", 0 } { "", 0 }
}; };
...@@ -409,7 +412,7 @@ static int __devinit check_resources(struct pnp_dev *dev) ...@@ -409,7 +412,7 @@ static int __devinit check_resources(struct pnp_dev *dev)
* PnP modems, alternatively we must hardcode all modems in pnp_devices[] * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
* table. * table.
*/ */
static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags) static int __devinit serial_pnp_guess_board(struct pnp_dev *dev)
{ {
if (!(check_name(pnp_dev_name(dev)) || if (!(check_name(pnp_dev_name(dev)) ||
(dev->card && check_name(dev->card->name)))) (dev->card && check_name(dev->card->name))))
...@@ -428,7 +431,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) ...@@ -428,7 +431,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
int ret, line, flags = dev_id->driver_data; int ret, line, flags = dev_id->driver_data;
if (flags & UNKNOWN_DEV) { if (flags & UNKNOWN_DEV) {
ret = serial_pnp_guess_board(dev, &flags); ret = serial_pnp_guess_board(dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
...@@ -436,7 +439,10 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) ...@@ -436,7 +439,10 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
memset(&uart, 0, sizeof(uart)); memset(&uart, 0, sizeof(uart));
if (pnp_irq_valid(dev, 0)) if (pnp_irq_valid(dev, 0))
uart.port.irq = pnp_irq(dev, 0); uart.port.irq = pnp_irq(dev, 0);
if (pnp_port_valid(dev, 0)) { if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) {
uart.port.iobase = pnp_port_start(dev, 2);
uart.port.iotype = UPIO_PORT;
} else if (pnp_port_valid(dev, 0)) {
uart.port.iobase = pnp_port_start(dev, 0); uart.port.iobase = pnp_port_start(dev, 0);
uart.port.iotype = UPIO_PORT; uart.port.iotype = UPIO_PORT;
} else if (pnp_mem_valid(dev, 0)) { } else if (pnp_mem_valid(dev, 0)) {
...@@ -451,6 +457,10 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) ...@@ -451,6 +457,10 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
"Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n", "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
uart.port.iobase, uart.port.mapbase, uart.port.irq, uart.port.iotype); uart.port.iobase, uart.port.mapbase, uart.port.irq, uart.port.iotype);
#endif #endif
if (flags & CIR_PORT) {
uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE;
uart.port.type = PORT_8250_CIR;
}
uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE) if (pnp_irq_flags(dev, 0) & IORESOURCE_IRQ_SHAREABLE)
...@@ -459,7 +469,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) ...@@ -459,7 +469,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
uart.port.dev = &dev->dev; uart.port.dev = &dev->dev;
line = serial8250_register_8250_port(&uart); line = serial8250_register_8250_port(&uart);
if (line < 0) if (line < 0 || (flags & CIR_PORT))
return -ENODEV; return -ENODEV;
pnp_set_drvdata(dev, (void *)((long)line + 1)); pnp_set_drvdata(dev, (void *)((long)line + 1));
......
...@@ -48,7 +48,8 @@ ...@@ -48,7 +48,8 @@
#define PORT_TEGRA 20 /* NVIDIA Tegra internal UART */ #define PORT_TEGRA 20 /* NVIDIA Tegra internal UART */
#define PORT_XR17D15X 21 /* Exar XR17D15x UART */ #define PORT_XR17D15X 21 /* Exar XR17D15x UART */
#define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */ #define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */
#define PORT_MAX_8250 22 /* max port ID */ #define PORT_8250_CIR 23 /* CIR infrared port, has its own driver */
#define PORT_MAX_8250 23 /* max port ID */
/* /*
* ARM specific type numbers. These are not currently guaranteed * ARM specific type numbers. These are not currently guaranteed
......
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