linux-serial.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/1] drivers: tty: imx: fix flags of rs485 not work properly
@ 2024-09-06  2:19 LiangCheng Wang
  2024-09-06  6:03 ` Jiri Slaby
  0 siblings, 1 reply; 3+ messages in thread
From: LiangCheng Wang @ 2024-09-06  2:19 UTC (permalink / raw)
  To: shawnguo
  Cc: s.hauer, gregkh, jirislaby, kernel, festevam, u.kleine-koenig,
	cniedermaier, l.sanfilippo, linux, stefan.eichenberger, tglx,
	rickaran, zaq14760, linux-kernel, linux-serial, imx,
	linux-arm-kernel

The rs485.flags are lost in functions such as imx_uart_stop_tx(),
causing the function of RS485 to be invalid when using the
serial port as the RS485 port. Use a variable to store the state to
avoid this issue.

Signed-off-by: LiangCheng Wang <zaq14760@gmail.com>
---
 drivers/tty/serial/imx.c | 35 ++++++++++++++++++-----------------
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 67d4a72eda77..346bbd21536b 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -209,7 +209,7 @@ struct imx_port {
 	const struct imx_uart_data *devdata;
 
 	struct mctrl_gpios *gpios;
-
+	int flags;
 	/* counter to stop 0xff flood */
 	int idle_counter;
 
@@ -434,7 +434,7 @@ static void imx_uart_stop_tx(struct uart_port *port)
 	imx_uart_writel(sport, ucr4, UCR4);
 
 	/* in rs485 mode disable transmitter */
-	if (port->rs485.flags & SER_RS485_ENABLED) {
+	if (sport->flags & SER_RS485_ENABLED) {
 		if (sport->tx_state == SEND) {
 			sport->tx_state = WAIT_AFTER_SEND;
 
@@ -454,7 +454,7 @@ static void imx_uart_stop_tx(struct uart_port *port)
 			hrtimer_try_to_cancel(&sport->trigger_start_tx);
 
 			ucr2 = imx_uart_readl(sport, UCR2);
-			if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+			if (sport->flags & SER_RS485_RTS_AFTER_SEND)
 				imx_uart_rts_active(sport, &ucr2);
 			else
 				imx_uart_rts_inactive(sport, &ucr2);
@@ -490,8 +490,8 @@ static void imx_uart_stop_rx_with_loopback_ctrl(struct uart_port *port, bool loo
 	imx_uart_writel(sport, ucr4, UCR4);
 
 	/* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */
-	if (port->rs485.flags & SER_RS485_ENABLED &&
-	    port->rs485.flags & SER_RS485_RTS_ON_SEND &&
+	if (sport->flags & SER_RS485_ENABLED &&
+	    sport->flags & SER_RS485_RTS_ON_SEND &&
 	    sport->have_rtscts && !sport->have_rtsgpio && loopback) {
 		uts = imx_uart_readl(sport, imx_uart_uts_reg(sport));
 		uts |= UTS_LOOP;
@@ -604,7 +604,7 @@ static void imx_uart_dma_tx_callback(void *data)
 	if (!kfifo_is_empty(&tport->xmit_fifo) &&
 			!uart_tx_stopped(&sport->port))
 		imx_uart_dma_tx(sport);
-	else if (sport->port.rs485.flags & SER_RS485_ENABLED) {
+	else if (sport->flags & SER_RS485_ENABLED) {
 		u32 ucr4 = imx_uart_readl(sport, UCR4);
 		ucr4 |= UCR4_TCEN;
 		imx_uart_writel(sport, ucr4, UCR4);
@@ -681,10 +681,10 @@ static void imx_uart_start_tx(struct uart_port *port)
 	 * imx_uart_stop_tx(), but tx_state is still SEND.
 	 */
 
-	if (port->rs485.flags & SER_RS485_ENABLED) {
+	if (sport->flags & SER_RS485_ENABLED) {
 		if (sport->tx_state == OFF) {
 			u32 ucr2 = imx_uart_readl(sport, UCR2);
-			if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
+			if (sport->flags & SER_RS485_RTS_ON_SEND)
 				imx_uart_rts_active(sport, &ucr2);
 			else
 				imx_uart_rts_inactive(sport, &ucr2);
@@ -695,7 +695,7 @@ static void imx_uart_start_tx(struct uart_port *port)
 			 * with loopback enabled because that will make our
 			 * transmitted data being just looped to RX.
 			 */
-			if (!(port->rs485.flags & SER_RS485_RX_DURING_TX) &&
+			if (!(sport->flags & SER_RS485_RX_DURING_TX) &&
 			    !port->rs485_rx_during_tx_gpio)
 				imx_uart_stop_rx_with_loopback_ctrl(port, false);
 
@@ -1078,7 +1078,7 @@ static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	struct imx_port *sport = to_imx_port(port);
 	u32 ucr3, uts;
 
-	if (!(port->rs485.flags & SER_RS485_ENABLED)) {
+	if (!(sport->flags & SER_RS485_ENABLED)) {
 		u32 ucr2;
 
 		/*
@@ -1604,8 +1604,8 @@ static void imx_uart_shutdown(struct uart_port *port)
 	ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_RXDMAEN |
 		  UCR1_ATDMAEN | UCR1_SNDBRK);
 	/* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */
-	if (port->rs485.flags & SER_RS485_ENABLED &&
-	    port->rs485.flags & SER_RS485_RTS_ON_SEND &&
+	if (sport->flags & SER_RS485_ENABLED &&
+	    sport->flags & SER_RS485_RTS_ON_SEND &&
 	    sport->have_rtscts && !sport->have_rtsgpio) {
 		uts = imx_uart_readl(sport, imx_uart_uts_reg(sport));
 		uts |= UTS_LOOP;
@@ -1643,7 +1643,7 @@ static void imx_uart_shutdown(struct uart_port *port)
 	 * those cases, we have to wait for the hrtimer to fire and
 	 * complete the transition to OFF.
 	 */
-	loops = port->rs485.flags & SER_RS485_ENABLED ?
+	loops = sport->flags & SER_RS485_ENABLED ?
 		port->rs485.delay_rts_after_send : 0;
 	while (sport->tx_state != OFF && loops--) {
 		uart_port_unlock_irqrestore(&sport->port, flags);
@@ -1659,9 +1659,9 @@ static void imx_uart_shutdown(struct uart_port *port)
 		 * signal is inactive in order not to block other
 		 * devices.
 		 */
-		if (port->rs485.flags & SER_RS485_ENABLED) {
+		if (sport->flags & SER_RS485_ENABLED) {
 			ucr2 = imx_uart_readl(sport, UCR2);
-			if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+			if (sport->flags & SER_RS485_RTS_AFTER_SEND)
 				imx_uart_rts_active(sport, &ucr2);
 			else
 				imx_uart_rts_inactive(sport, &ucr2);
@@ -1749,13 +1749,13 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
 	if (!sport->have_rtscts)
 		termios->c_cflag &= ~CRTSCTS;
 
-	if (port->rs485.flags & SER_RS485_ENABLED) {
+	if (sport->flags & SER_RS485_ENABLED) {
 		/*
 		 * RTS is mandatory for rs485 operation, so keep
 		 * it under manual control and keep transmitter
 		 * disabled.
 		 */
-		if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+		if (sport->flags & SER_RS485_RTS_AFTER_SEND)
 			imx_uart_rts_active(sport, &ucr2);
 		else
 			imx_uart_rts_inactive(sport, &ucr2);
@@ -2394,6 +2394,7 @@ static int imx_uart_probe(struct platform_device *pdev)
 	}
 
 	ret = uart_get_rs485_mode(&sport->port);
+	sport->flags = sport->port.rs485.flags;
 	if (ret)
 		goto err_clk;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 1/1] drivers: tty: imx: fix flags of rs485 not work properly
  2024-09-06  2:19 [PATCH 1/1] drivers: tty: imx: fix flags of rs485 not work properly LiangCheng Wang
@ 2024-09-06  6:03 ` Jiri Slaby
  2024-09-20 15:58   ` Ilpo Järvinen
  0 siblings, 1 reply; 3+ messages in thread
From: Jiri Slaby @ 2024-09-06  6:03 UTC (permalink / raw)
  To: shawnguo, LiangCheng Wang
  Cc: s.hauer, gregkh, kernel, festevam, u.kleine-koenig, cniedermaier,
	l.sanfilippo, linux, stefan.eichenberger, tglx, rickaran,
	linux-kernel, linux-serial, imx, linux-arm-kernel

It seems gmail refuses to send this to zaq14760@gmail.com (the author).

On 06. 09. 24, 4:19, LiangCheng Wang wrote:
> The rs485.flags are lost in functions such as imx_uart_stop_tx(),
> causing the function of RS485 to be invalid when using the
> serial port as the RS485 port. Use a variable to store the state to
> avoid this issue.

AFAICT, this feels rather wrong. Any rs485 experts around?

At minimum, how are the flags "lost" and why this does not matter to 
other drivers?

> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -209,7 +209,7 @@ struct imx_port {
>   	const struct imx_uart_data *devdata;
>   
>   	struct mctrl_gpios *gpios;
> -
> +	int flags;

Definitely not int for flags.

thanks,
-- 
js
suse labs


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH 1/1] drivers: tty: imx: fix flags of rs485 not work properly
  2024-09-06  6:03 ` Jiri Slaby
@ 2024-09-20 15:58   ` Ilpo Järvinen
  0 siblings, 0 replies; 3+ messages in thread
From: Ilpo Järvinen @ 2024-09-20 15:58 UTC (permalink / raw)
  To: Jiri Slaby, LiangCheng Wang
  Cc: shawnguo, s.hauer, Greg Kroah-Hartman, kernel, festevam,
	u.kleine-koenig, cniedermaier, l.sanfilippo, linux,
	stefan.eichenberger, tglx, rickaran, LKML, linux-serial, imx,
	linux-arm-kernel

On Fri, 6 Sep 2024, Jiri Slaby wrote:

> It seems gmail refuses to send this to zaq14760@gmail.com (the author).
> 
> On 06. 09. 24, 4:19, LiangCheng Wang wrote:
> > The rs485.flags are lost in functions such as imx_uart_stop_tx(),
> > causing the function of RS485 to be invalid when using the
> > serial port as the RS485 port. Use a variable to store the state to
> > avoid this issue.
> 
> AFAICT, this feels rather wrong. Any rs485 experts around?

It is wrong. The patch makes no sense at all and prevents 
reconfiguring/setting rs485 from userspace.

> At minimum, how are the flags "lost" and why this does not matter to other
> drivers?

Perhaps some userspace program is altering rs485 settings, definitely 
nothing in imx_uart_stop_tx() writes to it. I'm skeptical it would be a 
problem in the kernel, especially given the patch that is supposed to 
"avoid the issue" (whatever the issue is).

> > --- a/drivers/tty/serial/imx.c
> > +++ b/drivers/tty/serial/imx.c
> > @@ -209,7 +209,7 @@ struct imx_port {
> >   	const struct imx_uart_data *devdata;
> >     	struct mctrl_gpios *gpios;
> > -
> > +	int flags;
> 
> Definitely not int for flags.

Driver is not supposed to duplicate the rs485 flags at all.

-- 
 i.


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-09-20 15:58 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-09-06  2:19 [PATCH 1/1] drivers: tty: imx: fix flags of rs485 not work properly LiangCheng Wang
2024-09-06  6:03 ` Jiri Slaby
2024-09-20 15:58   ` Ilpo Järvinen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).