8250_omap: rs485 ioctl inconsistent.

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

 



I have observed inconsistent behavior regarding the rs485 ioctls when closing and opening the port.

I am using the v4.8 kernel (but this is present in 4.6 too) on an ARM device using the 8250_omap driver (the new one inside the tty/serial/8250/ folder). The rs485 transceiver is connected in a way that receives with the RTS pin high and it sends with the pin low.

This is the sequence that looks problematic:

Normal behavior (first run)

1-Open the serial device (fopen). UART_EFR_RTS is cleared twice.
2-Set ioctl to enable rs485 (TIOCSRS485). In our case we need to set the "SER_RS485_RTS_ON_SEND" flag and to leave the "SER_RS485_RTS_AFTER_SEND"
  cleared. UART_MCR_RTS is cleared.
3-Operate normally: the serial port works.
4-Close the serial port (fclose). UART_EFR_RTS is cleared.

Suspect behavior (second run)

5-Open the serial device again (fopen). UART_EFR_RTS is cleared twice. No UART_MCR_RTS modification.
6-Get the rs485 cfg through ioctl (TIOCGRS485). rs485 is reported as enabled.
7-Operate: The serial device can't receive.

It doesn't make a difference if I try to enable rs485 (TIOCSRS485) after step 6: it still doesn't work; the driver sees that rs485 is active and doesn't modify the RTS pin (UART_MCR_RTS).

Looking with the oscilloscope we see that on the first (successful) run the RTS line starts high, goes low for an instant between the fopen and the ioctl call and then goes high again. On the second run (failing) the line goes low as soon as we open the file descriptor and it's never set high again.

If between 6 and 7 we run TIOCSRS485 to disable rs485 and then we re-enable it again we "cheat" the driver to issue a UART_MCR_RTS and everything works as it should. This __awful__ workaround against v4.8 makes things work. Just for clarification purposes.

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 9fc1533..0845111 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1753,8 +1753,20 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
         */
 err_unlock:
        mutex_unlock(&port->mutex);
-       if (retval == 0)
+       if (retval == 0) {
                retval = tty_port_block_til_ready(port, tty, filp);
+               if (retval == 0 && uport->rs485_config) {
+                       struct serial_rs485 off, old;
+                       memset (&off, 0, sizeof (off));
+                       mutex_lock (&port->mutex);
+                       if ((uport->rs485.flags & SER_RS485_ENABLED)) {
+                               old = uport->rs485;
+                               uport->rs485_config (uport, &off);
+                               uport->rs485_config (uport, &old);
+                       }
+                       mutex_unlock (&port->mutex);
+               }
+       }
 end:
        return retval;
 }

Is this a bug? If positive, is there a more fine-grained approach to solve this?--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[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