serial/8250: Add support for RS485 IOCTLs
authorRicardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Tue, 5 Aug 2014 09:45:59 +0000 (11:45 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 8 Sep 2014 22:26:26 +0000 (15:26 -0700)
This patch allow the users of the 8250 infrastructure to define a
handler for RS485 configration.

If no handler is defined the 8250 driver will work as usual.

Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Acked-by: Alan Cox <alan@linux.intel.com>
--
v2:Change suggested by Alan "One Thousand Gnomes":
- Move rs485 structure further down on the uart_8250_port structure

 drivers/tty/serial/8250/8250_core.c | 39 +++++++++++++++++++++++++++++++++++++
 include/linux/serial_8250.h         |  3 +++
 2 files changed, 42 insertions(+)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/8250/8250_core.c
include/linux/serial_8250.h

index 1d42dba6121d029eb9e900df9488b0d3a30f54dd..b28ed1beb50f556f04b4f3f0b42b0301049cfc55 100644 (file)
@@ -2843,6 +2843,42 @@ serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
        return 0;
 }
 
+static int serial8250_ioctl(struct uart_port *port, unsigned int cmd,
+                          unsigned long arg)
+{
+       struct uart_8250_port *up =
+               container_of(port, struct uart_8250_port, port);
+       int ret;
+       struct serial_rs485 rs485_config;
+
+       if (!up->rs485_config)
+               return -ENOIOCTLCMD;
+
+       switch (cmd) {
+       case TIOCSRS485:
+               if (copy_from_user(&rs485_config, (void __user *)arg,
+                                  sizeof(rs485_config)))
+                       return -EFAULT;
+
+               ret = up->rs485_config(up, &rs485_config);
+               if (ret)
+                       return ret;
+
+               memcpy(&up->rs485, &rs485_config, sizeof(rs485_config));
+
+               return 0;
+       case TIOCGRS485:
+               if (copy_to_user((void __user *)arg, &up->rs485,
+                                sizeof(up->rs485)))
+                       return -EFAULT;
+               return 0;
+       default:
+               break;
+       }
+
+       return -ENOIOCTLCMD;
+}
+
 static const char *
 serial8250_type(struct uart_port *port)
 {
@@ -2872,6 +2908,7 @@ static struct uart_ops serial8250_pops = {
        .request_port   = serial8250_request_port,
        .config_port    = serial8250_config_port,
        .verify_port    = serial8250_verify_port,
+       .ioctl          = serial8250_ioctl,
 #ifdef CONFIG_CONSOLE_POLL
        .poll_get_char = serial8250_get_poll_char,
        .poll_put_char = serial8250_put_poll_char,
@@ -3388,6 +3425,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
                uart->port.fifosize     = up->port.fifosize;
                uart->tx_loadsz         = up->tx_loadsz;
                uart->capabilities      = up->capabilities;
+               uart->rs485_config      = up->rs485_config;
+               uart->rs485             = up->rs485;
 
                /* Take tx_loadsz from fifosize if it wasn't set separately */
                if (uart->port.fifosize && !uart->tx_loadsz)
index f93649e22c438369983ec8a393da3f05d69bea76..6dd671765312e82bc24d3fe52972e45ec05cb34b 100644 (file)
@@ -96,10 +96,13 @@ struct uart_8250_port {
        unsigned char           msr_saved_flags;
 
        struct uart_8250_dma    *dma;
+       struct serial_rs485     rs485;
 
        /* 8250 specific callbacks */
        int                     (*dl_read)(struct uart_8250_port *);
        void                    (*dl_write)(struct uart_8250_port *, int);
+       int                     (*rs485_config)(struct uart_8250_port *,
+                                               struct serial_rs485 *rs485);
 };
 
 static inline struct uart_8250_port *up_to_u8250p(struct uart_port *up)