[PATCH RFC 1/2] serial: provide function to access registered uart_ports

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

 



This is a helper for the next patch. Don't merge, this is broken as
there is no working locking that prevents the port to go away while the
returned value is still in use.

Without-S-o-b-on-purpose-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx>
---
 drivers/tty/serial/serial_core.c | 39 ++++++++++++++++++++++++++++----
 include/linux/serial_core.h      |  3 +++
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 80bb56facfb6..9c923d744593 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2428,6 +2428,8 @@ static const struct tty_port_operations uart_port_ops = {
 	.shutdown	= uart_tty_port_shutdown,
 };
 
+static LIST_HEAD(uart_driver_list);
+
 /**
  *	uart_register_driver - register a driver with the uart core layer
  *	@drv: low level driver structure
@@ -2444,7 +2446,7 @@ static const struct tty_port_operations uart_port_ops = {
 int uart_register_driver(struct uart_driver *drv)
 {
 	struct tty_driver *normal;
-	int i, retval;
+	int i, retval = -ENOMEM;
 
 	BUG_ON(drv->state);
 
@@ -2487,16 +2489,21 @@ int uart_register_driver(struct uart_driver *drv)
 	}
 
 	retval = tty_register_driver(normal);
-	if (retval >= 0)
-		return retval;
+	if (retval < 0)
+		goto out_destroy_ports;
+
+	list_add(&drv->uart_driver_list, &uart_driver_list);
 
+	return 0;
+
+out_destroy_ports:
 	for (i = 0; i < drv->nr; i++)
 		tty_port_destroy(&drv->state[i].port);
 	put_tty_driver(normal);
 out_kfree:
 	kfree(drv->state);
 out:
-	return -ENOMEM;
+	return retval;
 }
 
 /**
@@ -2513,6 +2520,7 @@ void uart_unregister_driver(struct uart_driver *drv)
 	struct tty_driver *p = drv->tty_driver;
 	unsigned int i;
 
+	list_del(&drv->uart_driver_list);
 	tty_unregister_driver(p);
 	put_tty_driver(p);
 	for (i = 0; i < drv->nr; i++)
@@ -2522,6 +2530,29 @@ void uart_unregister_driver(struct uart_driver *drv)
 	drv->tty_driver = NULL;
 }
 
+const struct uart_port *uart_get_port_by_name(const char *name)
+{
+	struct uart_driver *drv;
+	struct uart_state *ustate;
+
+	list_for_each_entry(drv, &uart_driver_list, uart_driver_list) {
+		size_t drvdevnamelen = strlen(drv->dev_name);
+		int portno, ret;
+
+		if (strncmp(drv->dev_name, name, drvdevnamelen))
+			continue;
+
+		ret = kstrtoint(name + drvdevnamelen, 10, &portno);
+		if (ret < 0 || portno < 0 || portno >= drv->nr)
+			continue;
+
+		return drv->state[portno].uart_port;
+	}
+
+	return NULL;
+}
+
+
 struct tty_driver *uart_console_device(struct console *co, int *index)
 {
 	struct uart_driver *p = co->data;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 406edae44ca3..dd203a19e0f2 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -323,6 +323,7 @@ struct uart_driver {
 	 */
 	struct uart_state	*state;
 	struct tty_driver	*tty_driver;
+	struct list_head	uart_driver_list;
 };
 
 void uart_write_wakeup(struct uart_port *port);
@@ -421,6 +422,8 @@ int uart_add_one_port(struct uart_driver *reg, struct uart_port *port);
 int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port);
 int uart_match_port(struct uart_port *port1, struct uart_port *port2);
 
+const struct uart_port *uart_get_port_by_name(const char *name);
+
 /*
  * Power Management
  */
-- 
2.19.1




[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