All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alan Cox <alan@lxorguk.ukuu.org.uk>
To: linux-serial@vger.kernel.org
Subject: [RFC 3/5] 8250: register upio users
Date: Fri, 18 Mar 2011 15:25:38 +0000	[thread overview]
Message-ID: <20110318152529.10657.10613.stgit@bob.linux.org.uk> (raw)
In-Reply-To: <20110318152145.10657.23718.stgit@bob.linux.org.uk>

From: Alan Cox <alan@linux.intel.com>

We need to do this so we can continue to offer the setserial upio interface
while dumping I/O methods back out into the drivers.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/tty/serial/8250.c   |  103 ++++++++++++++++++++++++++++++-------------
 include/linux/serial_8250.h |    4 ++
 2 files changed, 77 insertions(+), 30 deletions(-)


diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index c3e56a7..89a00d1 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -612,46 +612,87 @@ static const struct serial8250_ops rm9k_ops = {
 	.serial_dl_write = rm9k_serial_dl_write
 };
 
-/* This needs to move to a table where drivers register their ops. Needs
-   some thought on the module count side */
+	
+static const struct serial8250_ops *upio_ops[UPIO_MAX + 1] = {
+	/* We rely upon pio_ops being built in */
+	&pio_ops,	/* UPIO_PORT */
+	&hub6_ops,	/* UPIO_HUB6 */
+	&mem_ops,	/* UPIO_MEM */
+	&mem32_ops,	/* UPIO_MEM32 */
+	&au_ops,	/* UPIO_AU */
+	&tsi_ops,	/* UPIO_TSI */
+	&dwapb_ops,	/* UPIO_DWAPB */
+	&rm9k_ops,	/* UPIO_RM9000 */
+	&dwapb32_ops	/* UPIO_DWAPB32 */
+};
+
+static DEFINE_MUTEX(upio_mutex);
+
 static void set_io_from_upio(struct uart_port *p)
 {
 	struct uart_8250_port *up =
 		container_of(p, struct uart_8250_port, port);
 
-	switch (p->iotype) {
-	case UPIO_HUB6:
-		up->ops = &hub6_ops;
-		break;
-	case UPIO_MEM:
-		up->ops = &mem_ops;
-		break;
-	case UPIO_RM9000:
-		up->ops = &rm9k_ops;
-		break;
-	case UPIO_MEM32:
-		up->ops = &mem32_ops;
-		break;
-	case UPIO_AU:
-		up->ops = &au_ops;
-		break;
-	case UPIO_TSI:
-		up->ops = &tsi_ops;
-		break;
-	case UPIO_DWAPB:
-		up->ops = &dwapb_ops;
-		break;
-	case UPIO_DWAPB32:
-		up->ops = &dwapb32_ops;
-		break;
-	default:
+	mutex_lock(&upio_mutex);
+	if (p->iotype > UPIO_MAX) {
+		WARN_ON(1);
 		up->ops = &pio_ops;
-		break;
+		p->iotype = UPIO_PORT;
+	}
+	/* up->ops may differ from up->cur_iotype ops
+	   For now work off cur_iotype, we should address this better later */
+	module_put(upio_ops[up->cur_iotype]->owner);
+	up->ops = upio_ops[p->iotype];
+	if (up->ops == NULL || !try_module_get(up->ops->owner)) {
+		up->ops = &pio_ops;
+		p->iotype = UPIO_PORT;
 	}
+		
 	/* Remember loaded iotype */
 	up->cur_iotype = p->iotype;
+	mutex_unlock(&upio_mutex);
 }
 
+/**
+ *	serial8250_upio_register	-	register UPIO methods
+ *	@upio: upio number
+ *	@ops: operations for this upio
+ *
+ *	Registers a set of upio operations and makes them available via
+ *	the serial configuration interface for tty devices, and via the
+ *	registration interfaces via upio value setting. Unless there are
+ *	specific reasons new drivers should pass an ops structure directly
+ *	instead.
+ */
+int serial8250_upio_register(int upio, struct serial8250_ops *ops)
+{
+	int ret = 0;
+	mutex_lock(&upio_mutex);
+	if (upio < 1 || upio > UPIO_MAX)
+		ret = -EINVAL;
+	else if (upio_ops[upio])
+		ret = -EBUSY;
+	else
+		upio_ops[upio] = ops;
+	mutex_unlock(&upio_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(serial8250_upio_register);
+
+int serial8250_upio_unregister(int upio)
+{
+	int ret = 0;
+	mutex_lock(&upio_mutex);
+	if (upio_ops[upio] == NULL) {
+		WARN_ON(1);
+		ret = -EINVAL;
+	}
+	upio_ops[upio] = NULL;
+	mutex_unlock(&upio_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(serial8250_upio_unregister);
+
 static void
 serial_out_sync(struct uart_8250_port *up, int offset, int value)
 {
@@ -3305,7 +3346,7 @@ int serial8250_register_port(struct uart_port *port,
 
 		set_io_from_upio(&uart->port);
 		if (ops)
-			uart->port.ops = ops;
+			uart->ops = ops;
 
 		if (serial8250_isa_config != NULL)
 			serial8250_isa_config(0, &uart->port,
@@ -3337,6 +3378,8 @@ void serial8250_unregister_port(int line)
 	if (serial8250_isa_devs) {
 		uart->port.flags &= ~UPF_BOOT_AUTOCONF;
 		uart->port.type = PORT_UNKNOWN;
+		uart->port.iotype = UPIO_PORT;
+		set_io_from_upio(&uart->port);
 		uart->port.dev = &serial8250_isa_devs->dev;
 		uart_add_one_port(&serial8250_reg, &uart->port);
 	} else {
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 15806bb..30d4f62 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -24,6 +24,7 @@ struct serial8250_ops {
 			      unsigned old);
 	unsigned int	(*serial_dl_read)(struct uart_port *);
 	void		(*serial_dl_write)(struct uart_port *, unsigned int);
+	struct module 	*owner;
 };
 
 /*
@@ -99,4 +100,7 @@ static inline int __deprecated early_serial_setup(struct uart_port *port)
         return serial8250_early_setup(port, NULL);
 }
 
+extern int serial8250_upio_register(int upio, struct serial8250_ops *ops);
+extern int serial8250_upio_unregister(int upio);
+
 #endif


  parent reply	other threads:[~2011-03-18 15:45 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-18 15:24 [RFC 0/5] Starting to pull out the I/O operations Alan Cox
2011-03-18 15:24 ` [RFC 1/5] 8250: Make serial_dl_write a port operation Alan Cox
2011-03-18 15:25 ` [RFC 2/5] 8250: introduce the idea of an operations struct for an 8250 port Alan Cox
2011-03-18 15:25 ` Alan Cox [this message]
2011-03-18 15:25 ` [RFC 4/5] 8250: evict the hub6 I/O operations Alan Cox
2011-03-18 15:26 ` [RFC 5/5] 8250: extract out the "odd" port types Alan Cox
2011-03-18 20:04 ` [RFC 0/5] Starting to pull out the I/O operations Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110318152529.10657.10613.stgit@bob.linux.org.uk \
    --to=alan@lxorguk.ukuu.org.uk \
    --cc=linux-serial@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.