greybus: uart-gb: handle throttle/unthrottle properly
authorGreg Kroah-Hartman <greg@kroah.com>
Wed, 19 Nov 2014 22:23:00 +0000 (14:23 -0800)
committerGreg Kroah-Hartman <greg@kroah.com>
Thu, 20 Nov 2014 00:47:24 +0000 (16:47 -0800)
This hooks up throttle/unthrottle to properly toggle the RTS line or do
XON/XOFF if that is how the port is set up.

Note, if the UART itself can handle XON/XOFF, we would need to send the
correct character down to it, to have the firmware in the device set up
the chip to use it automatically when needed.  The odds of someone
wanting to use this type of flow control is slim, so this isn't
implemented at this point in time.

Also fill in a few more fields in the get_serial_info ioctl, to make
tools like stty(1) happier.

Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
drivers/staging/greybus/uart-gb.c

index d01956a..460947e 100644 (file)
@@ -116,10 +116,7 @@ struct gb_tty {
        u16 cport_id;
        unsigned int minor;
        unsigned char clocal;
-       unsigned int throttled:1;
-       unsigned int throttle_req:1;
        bool disconnected;
-       int writesize;          // FIXME - set this somehow.
        spinlock_t read_lock;
        spinlock_t write_lock;
        struct async_icount iocount;
@@ -567,25 +564,39 @@ static int gb_tty_tiocmset(struct tty_struct *tty, unsigned int set,
 static void gb_tty_throttle(struct tty_struct *tty)
 {
        struct gb_tty *gb_tty = tty->driver_data;
+       unsigned char stop_char;
+       int retval;
+
+       if (I_IXOFF(tty)) {
+               stop_char = STOP_CHAR(tty);
+               retval = gb_tty_write(tty, &stop_char, 1);
+               if (retval <= 0)
+                       return;
+       }
+
+       if (tty->termios.c_cflag & CRTSCTS) {
+               gb_tty->ctrlout &= ~GB_UART_CTRL_RTS;
+               retval = send_control(gb_tty, gb_tty->ctrlout);
+       }
 
-       spin_lock_irq(&gb_tty->read_lock);
-       gb_tty->throttle_req = 1;
-       spin_unlock_irq(&gb_tty->read_lock);
 }
 
 static void gb_tty_unthrottle(struct tty_struct *tty)
 {
        struct gb_tty *gb_tty = tty->driver_data;
-       unsigned int was_throttled;
+       unsigned char start_char;
+       int retval;
 
-       spin_lock_irq(&gb_tty->read_lock);
-       was_throttled = gb_tty->throttled;
-       gb_tty->throttle_req = 0;
-       gb_tty->throttled = 0;
-       spin_unlock_irq(&gb_tty->read_lock);
+       if (I_IXOFF(tty)) {
+               start_char = START_CHAR(tty);
+               retval = gb_tty_write(tty, &start_char, 1);
+               if (retval <= 0)
+                       return;
+       }
 
-       if (was_throttled) {
-               // FIXME - send more data
+       if (tty->termios.c_cflag & CRTSCTS) {
+               gb_tty->ctrlout |= GB_UART_CTRL_RTS;
+               retval = send_control(gb_tty, gb_tty->ctrlout);
        }
 }
 
@@ -598,9 +609,11 @@ static int get_serial_info(struct gb_tty *gb_tty,
                return -EINVAL;
 
        memset(&tmp, 0, sizeof(tmp));
-       tmp.flags = ASYNC_LOW_LATENCY;
-       tmp.xmit_fifo_size = gb_tty->writesize;
-       tmp.baud_base = 0;      // FIXME
+       tmp.flags = ASYNC_LOW_LATENCY | ASYNC_SKIP_TEST;
+       tmp.type = PORT_16550A;
+       tmp.line = gb_tty->minor;
+       tmp.xmit_fifo_size = 16;
+       tmp.baud_base = 9600;
        tmp.close_delay = gb_tty->port.close_delay / 10;
        tmp.closing_wait = gb_tty->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
                                ASYNC_CLOSING_WAIT_NONE : gb_tty->port.closing_wait / 10;