[PATCH -next 15/17] serial: 8250: Decouple RSA probe

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Prepare for 8250 split; separate RSA probe and resource management
from base port operations. Override base port operations for the
config_port(), request_port() and release_port() methods to
implement the optional RSA probe and resource management only in
the universal/legacy 8250 driver.

Introduce 'probe' flags for 8250 ports, which allows drivers higher
up the driver stack to enable optional probes.

Signed-off-by: Peter Hurley <peter@xxxxxxxxxxxxxxxxxx>
---
 drivers/tty/serial/8250/8250.h      |   3 -
 drivers/tty/serial/8250/8250_core.c | 112 ++++++++++++++++++++++++------------
 include/linux/serial_8250.h         |   2 +
 3 files changed, 78 insertions(+), 39 deletions(-)

diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 89a0457..7713410 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -84,9 +84,6 @@ struct serial8250_config {
 #define UART_BUG_THRE	(1 << 3)	/* UART has buggy THRE reassertion */
 #define UART_BUG_PARITY	(1 << 4)	/* UART mishandles parity if FIFO enabled */
 
-#define PROBE_RSA	(1 << 0)
-#define PROBE_ANY	(~0)
-
 #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
 
 #ifdef CONFIG_SERIAL_8250_SHARE_IRQ
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 72c9f2d..4e6bf09 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1105,7 +1105,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
  * whether or not this UART is a 16550A or not, since this will
  * determine whether or not we can use its FIFO features or not.
  */
-static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
+static void autoconfig(struct uart_8250_port *up)
 {
 	unsigned char status1, scratch, scratch2, scratch3;
 	unsigned char save_lcr, save_mcr;
@@ -1228,7 +1228,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
 	/*
 	 * Only probe for RSA ports if we got the region.
 	 */
-	if (port->type == PORT_16550A && probeflags & PROBE_RSA &&
+	if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA &&
 	    __enable_rsa(up))
 		port->type = PORT_RSA;
 #endif
@@ -2833,10 +2833,6 @@ static void serial8250_release_port(struct uart_port *port)
 	struct uart_8250_port *up = up_to_u8250p(port);
 
 	serial8250_release_std_resource(up);
-#ifdef CONFIG_SERIAL_8250_RSA
-	if (port->type == PORT_RSA)
-		serial8250_release_rsa_resource(up);
-#endif
 }
 
 static int serial8250_request_port(struct uart_port *port)
@@ -2848,13 +2844,6 @@ static int serial8250_request_port(struct uart_port *port)
 		return -ENODEV;
 
 	ret = serial8250_request_std_resource(up);
-#ifdef CONFIG_SERIAL_8250_RSA
-	if (ret == 0 && port->type == PORT_RSA) {
-		ret = serial8250_request_rsa_resource(up);
-		if (ret < 0)
-			serial8250_release_std_resource(up);
-	}
-#endif
 
 	return ret;
 }
@@ -3002,7 +2991,6 @@ static void register_dev_spec_attr_grp(struct uart_8250_port *up)
 static void serial8250_config_port(struct uart_port *port, int flags)
 {
 	struct uart_8250_port *up = up_to_u8250p(port);
-	int probeflags = 0;
 	int ret;
 
 	if (port->type == PORT_8250_CIR)
@@ -3016,28 +3004,11 @@ static void serial8250_config_port(struct uart_port *port, int flags)
 	if (ret < 0)
 		return;
 
-#ifdef CONFIG_SERIAL_8250_RSA
-	if (port->type == PORT_RSA) {
-		if (serial8250_request_rsa_resource(up) == 0)
-			probeflags |= PROBE_RSA;
-	} else if (flags & UART_CONFIG_TYPE) {
-		int i;
-
-		for (i = 0 ; i < probe_rsa_count; ++i) {
-			if (probe_rsa[i] == port->iobase) {
-				if (serial8250_request_rsa_resource(up) == 0)
-					probeflags |= PROBE_RSA;
-				break;
-			}
-		}
-	}
-#endif
-
 	if (port->iotype != up->cur_iotype)
 		set_io_from_upio(port);
 
 	if (flags & UART_CONFIG_TYPE)
-		autoconfig(up, probeflags);
+		autoconfig(up);
 
 	/* if access method is AU, it is a 16550 with a quirk */
 	if (port->type == PORT_16550A && port->iotype == UPIO_AU)
@@ -3050,10 +3021,6 @@ static void serial8250_config_port(struct uart_port *port, int flags)
 	if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
 		autoconfig_irq(up);
 
-#ifdef CONFIG_SERIAL_8250_RSA
-	if (port->type != PORT_RSA && probeflags & PROBE_RSA)
-		serial8250_release_rsa_resource(up);
-#endif
 	if (port->type == PORT_UNKNOWN)
 		serial8250_release_std_resource(up);
 
@@ -3114,6 +3081,9 @@ static struct uart_ops serial8250_pops = {
 #endif
 };
 
+static const struct uart_ops *base_ops;
+static struct uart_ops univ8250_port_ops;
+
 static const struct uart_8250_ops univ8250_driver_ops = {
 	.setup_irq	= univ8250_setup_irq,
 	.release_irq	= univ8250_release_irq,
@@ -3185,6 +3155,69 @@ static void serial8250_set_defaults(struct uart_8250_port *up)
 	}
 }
 
+#ifdef CONFIG_SERIAL_8250_RSA
+
+static void univ8250_config_port(struct uart_port *port, int flags)
+{
+	struct uart_8250_port *up = up_to_u8250p(port);
+
+	up->probe &= ~UART_PROBE_RSA;
+	if (port->type == PORT_RSA) {
+		if (serial8250_request_rsa_resource(up) == 0)
+			up->probe |= UART_PROBE_RSA;
+	} else if (flags & UART_CONFIG_TYPE) {
+		int i;
+
+		for (i = 0; i < probe_rsa_count; i++) {
+			if (probe_rsa[i] == up->port.iobase) {
+				if (serial8250_request_rsa_resource(up) == 0)
+					up->probe |= UART_PROBE_RSA;
+				break;
+			}
+		}
+	}
+
+	base_ops->config_port(port, flags);
+
+	if (port->type != PORT_RSA && up->probe & UART_PROBE_RSA)
+		serial8250_release_rsa_resource(up);
+}
+
+static int univ8250_request_port(struct uart_port *port)
+{
+	struct uart_8250_port *up = up_to_u8250p(port);
+	int ret;
+
+	ret = base_ops->request_port(port);
+	if (ret == 0 && port->type == PORT_RSA) {
+		ret = serial8250_request_rsa_resource(up);
+		if (ret < 0)
+			base_ops->release_port(port);
+	}
+
+	return ret;
+}
+
+static void univ8250_release_port(struct uart_port *port)
+{
+	struct uart_8250_port *up = up_to_u8250p(port);
+
+	if (port->type == PORT_RSA)
+		serial8250_release_rsa_resource(up);
+	base_ops->release_port(port);
+}
+
+static void univ8250_rsa_support(struct uart_ops *ops)
+{
+	ops->config_port  = univ8250_config_port;
+	ops->request_port = univ8250_request_port;
+	ops->release_port = univ8250_release_port;
+}
+
+#else
+#define univ8250_rsa_support(x)		do { } while (0)
+#endif /* CONFIG_SERIAL_8250_RSA */
+
 static void __init serial8250_isa_init_ports(void)
 {
 	struct uart_8250_port *up;
@@ -3204,6 +3237,9 @@ static void __init serial8250_isa_init_ports(void)
 
 		port->line = i;
 		serial8250_init_port(up);
+		if (!base_ops)
+			base_ops = port->ops;
+		port->ops = &univ8250_port_ops;
 
 		init_timer(&up->timer);
 		up->timer.function = serial8250_timeout;
@@ -3217,6 +3253,10 @@ static void __init serial8250_isa_init_ports(void)
 		up->mcr_force = ALPHA_KLUDGE_MCR;
 	}
 
+	/* chain base port ops to support Remote Supervisor Adapter */
+	univ8250_port_ops = *base_ops;
+	univ8250_rsa_support(&univ8250_port_ops);
+
 	if (share_irqs)
 		irqflag = IRQF_SHARED;
 
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 50735a9..78097e7 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -102,6 +102,8 @@ struct uart_8250_port {
 	unsigned char		canary;		/* non-zero during system sleep
 						 *   if no_console_suspend
 						 */
+	unsigned char		probe;
+#define UART_PROBE_RSA	(1 << 0)
 
 	/*
 	 * Some bits in registers are cleared on a read, so they must
-- 
2.3.0

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux