Re: [PATCH 2/8] serial: imx: fix breaking RTS/CTS handshake by mctrl change

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

 



Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx> writes:

> Hello,
>
> On Thu, May 30, 2019 at 06:29:44PM +0300, Sergey Organov wrote:
>> imx_set_mctrl() stop fiddling with UCR2_CTSC bit
>> 
>> Signed-off-by: Sergey Organov <sorganov@xxxxxxxxx>
>> ---
>>  drivers/tty/serial/imx.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>> 
>> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
>> index e9e812a..6577552 100644
>> --- a/drivers/tty/serial/imx.c
>> +++ b/drivers/tty/serial/imx.c
>> @@ -967,9 +967,9 @@ static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
>>  		u32 ucr2;
>>  
>>  		ucr2 = imx_uart_readl(sport, UCR2);
>> -		ucr2 &= ~(UCR2_CTS | UCR2_CTSC);
>> +		ucr2 &= ~UCR2_CTS;
>>  		if (mctrl & TIOCM_RTS)
>> -			ucr2 |= UCR2_CTS | UCR2_CTSC;
>> +			ucr2 |= UCR2_CTS;
>>  		imx_uart_writel(sport, ucr2, UCR2);
>>  	}
>
> I'm sure this patch is wrong. And your change log fails to point out
> what you want to achieve.

Sorry, I somehow thought it's obvious when in fact it appears it isn't.

When user calls ioctl() to set/clear TIOCM_RTS bit from user space, the
RTS/CTS automatic handshake must not be affected. Without this patch
setting TIOCM_RTS to logic 0 turns off RTS/CTS handshake in hardware,
and setting it to logic 1 turns on RTS/CTS handshake in hardware, that
is wrong thing to do in both cases.

I'm sure the patch is the right thing to do here (see below for more
discussion). Just stop fiddling with RTS/CTS handshake bit in
set_mctrl(), and it will work as expected.

>
> Independant of your patch I discussed a problem in imx_uart_set_mctrl()
> with Sascha and Russell (both added to Cc:) earlier this week. In the
> current implementation there are actually two problems.
>
> Currently imx_uart_set_mctrl does:
>
> 	if TIOCM_RTS is set:
> 		let the receiver control the RTS signal
> 	else:
> 		set RTS inactive

Worse. In fact it breaks current UCR2_CTSC state on both branches of the
if, and thus breaks correspondence between CRTSCTS and UCR2_CTSC that
the driver should preserve at all times.

> The bigger problem is that if the UART is configured not to use
> handshaking (CRTSCTS unset) the mode "let the receiver control the RTS
> signal" should not be used.

Once again, that's exactly why we need to stop touching UCR2_CTSC in
set_mctrl().

> The smaller (and irrelevant for correctness) problem is that setting
> UCR2_CTS is a no-op when UCR2_CTSC is also set.

It's not a problem at all. When user wants to drive RTS manually, he
turns off RTS/CTS handshake. When RTS/CTS handshake is turned on,
setting/clearing TIOCM_RTS usually has no effect on the level of the RTS
pin. 

>
> We think the right thing to do is:
>
> 	ucr2 = imx_uart_readl(sport, UCR2);
> 	ucr2 &= ~(UCR2_CTS | UCR2_CTSC);
>
> 	if (mctrl & TIOCM_RTS) {
> 		if (sport->crtscts)
> 			/* let the receiver control RTS */
> 			ucr2 |= UCR2_CTSC;
> 		else
> 			/* Force RTS active */
> 			ucr2 |= UCR2_CTS;
> 	} else {
> 		/* Force RTS inactive, i.e. CTS=0, CTSC=0 */
> 	}
>
> 	imx_uart_writel(sport, ucr2, UCR2);
>
> but AFAICT this isn't tested yet to an end in the use case that Sascha
> currently has and so there isn't a complete patch available yet.

This is still wrong, as it turns off RTS/CTS handshake in hardware on
TIOCM_RTS=0. Once again, set_mctrl() should not touch UCR2_CTSC, -- it's
as simple as that.

I still think it's rather what I did in the patch above is the right
thing to do. It's simple and does the job, no surprises.

-- Sergey



[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