serial: max310x: Assign port line automatically
authorAlexander Shiyan <shc_work@mail.ru>
Tue, 7 Jun 2016 15:59:27 +0000 (18:59 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 25 Jun 2016 20:55:35 +0000 (13:55 -0700)
This patch makes assignment of port line automatically,
so now user allow to use several MAX310X chips.

Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/max310x.c

index 347f6e8..9360801 100644 (file)
@@ -32,7 +32,7 @@
 #define MAX310X_NAME                   "max310x"
 #define MAX310X_MAJOR                  204
 #define MAX310X_MINOR                  209
-#define MAX310X_UART_NR                        4
+#define MAX310X_UART_NRMAX             16
 
 /* MAX310X register definitions */
 #define MAX310X_RHR_REG                        (0x00) /* RX FIFO */
@@ -279,9 +279,11 @@ static struct uart_driver max310x_uart = {
        .dev_name       = "ttyMAX",
        .major          = MAX310X_MAJOR,
        .minor          = MAX310X_MINOR,
-       .nr             = MAX310X_UART_NR,
+       .nr             = MAX310X_UART_NRMAX,
 };
 
+static DECLARE_BITMAP(max310x_lines, MAX310X_UART_NRMAX);
+
 static u8 max310x_port_read(struct uart_port *port, u8 reg)
 {
        struct max310x_port *s = dev_get_drvdata(port->dev);
@@ -600,9 +602,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
        unsigned int sts, ch, flag;
 
        if (unlikely(rxlen >= port->fifosize)) {
-               dev_warn_ratelimited(port->dev,
-                                    "Port %i: Possible RX FIFO overrun\n",
-                                    port->line);
+               dev_warn_ratelimited(port->dev, "Possible RX FIFO overrun\n");
                port->icount.buf_overrun++;
                /* Ensure sanity of RX level */
                rxlen = port->fifosize;
@@ -1193,8 +1193,16 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
        mutex_init(&s->mutex);
 
        for (i = 0; i < devtype->nr; i++) {
+               unsigned int line;
+
+               line = find_first_zero_bit(max310x_lines, MAX310X_UART_NRMAX);
+               if (line == MAX310X_UART_NRMAX) {
+                       ret = -ERANGE;
+                       goto out_uart;
+               }
+
                /* Initialize port data */
-               s->p[i].port.line       = i;
+               s->p[i].port.line       = line;
                s->p[i].port.dev        = dev;
                s->p[i].port.irq        = irq;
                s->p[i].port.type       = PORT_MAX310X;
@@ -1220,8 +1228,15 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
                INIT_WORK(&s->p[i].md_work, max310x_md_proc);
                /* Initialize queue for changing RS485 mode */
                INIT_WORK(&s->p[i].rs_work, max310x_rs_proc);
+
                /* Register port */
-               uart_add_one_port(&max310x_uart, &s->p[i].port);
+               ret = uart_add_one_port(&max310x_uart, &s->p[i].port);
+               if (ret) {
+                       s->p[i].port.dev = NULL;
+                       goto out_uart;
+               }
+               set_bit(line, max310x_lines);
+
                /* Go to suspend mode */
                devtype->power(&s->p[i].port, 0);
        }
@@ -1234,8 +1249,13 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
 
        dev_err(dev, "Unable to reguest IRQ %i\n", irq);
 
-       for (i = 0; i < devtype->nr; i++)
-               uart_remove_one_port(&max310x_uart, &s->p[i].port);
+out_uart:
+       for (i = 0; i < devtype->nr; i++) {
+               if (s->p[i].port.dev) {
+                       uart_remove_one_port(&max310x_uart, &s->p[i].port);
+                       clear_bit(s->p[i].port.line, max310x_lines);
+               }
+       }
 
        mutex_destroy(&s->mutex);
 
@@ -1255,6 +1275,7 @@ static int max310x_remove(struct device *dev)
                cancel_work_sync(&s->p[i].md_work);
                cancel_work_sync(&s->p[i].rs_work);
                uart_remove_one_port(&max310x_uart, &s->p[i].port);
+               clear_bit(s->p[i].port.line, max310x_lines);
                s->devtype->power(&s->p[i].port, 0);
        }
 
@@ -1347,6 +1368,8 @@ static int __init max310x_uart_init(void)
 {
        int ret;
 
+       bitmap_zero(max310x_lines, MAX310X_UART_NRMAX);
+
        ret = uart_register_driver(&max310x_uart);
        if (ret)
                return ret;