diff mbox

[2/7] serial: sh-sci: consider DR (data ready) bit adequately

Message ID 1481286971-16667-3-git-send-email-ulrich.hecht+renesas@gmail.com (mailing list archive)
State Superseded
Delegated to: Geert Uytterhoeven
Headers show

Commit Message

Ulrich Hecht Dec. 9, 2016, 12:36 p.m. UTC
To allow operation with a higher RX FIFO interrupt threshold in PIO
mode, it is necessary to consider the DR bit ("FIFO not full, but no
data received for 1.5 frames") as an indicator that data can be read.
Otherwise the driver will let data rot in the FIFO until the threshold
is reached.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/tty/serial/sh-sci.c | 9 +++++----
 drivers/tty/serial/sh-sci.h | 1 +
 2 files changed, 6 insertions(+), 4 deletions(-)

Comments

Geert Uytterhoeven Dec. 14, 2016, 1:45 p.m. UTC | #1
Hi Uli,

On Fri, Dec 9, 2016 at 1:36 PM, Ulrich Hecht
<ulrich.hecht+renesas@gmail.com> wrote:
> To allow operation with a higher RX FIFO interrupt threshold in PIO
> mode, it is necessary to consider the DR bit ("FIFO not full, but no
> data received for 1.5 frames") as an indicator that data can be read.
> Otherwise the driver will let data rot in the FIFO until the threshold
> is reached.
>
> Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>

> --- a/drivers/tty/serial/sh-sci.c
> +++ b/drivers/tty/serial/sh-sci.c
> @@ -677,7 +677,7 @@ static int sci_poll_get_char(struct uart_port *port)
>                 break;
>         } while (1);
>
> -       if (!(status & SCxSR_RDxF(port)))
> +       if (!(status & (SCxSR_RDxF(port) | SCxSR_DR(port))))
>                 return NO_POLL_CHAR;
>
>         c = serial_port_in(port, SCxRDR);

> --- a/drivers/tty/serial/sh-sci.h
> +++ b/drivers/tty/serial/sh-sci.h
> @@ -156,6 +156,7 @@ enum {
>  #define SCxSR_FER(port)                (((port)->type == PORT_SCI) ? SCI_FER    : SCIF_FER)
>  #define SCxSR_PER(port)                (((port)->type == PORT_SCI) ? SCI_PER    : SCIF_PER)
>  #define SCxSR_BRK(port)                (((port)->type == PORT_SCI) ? 0x00       : SCIF_BRK)
> +#define SCxSR_DR(port)         (((port)->type == PORT_SCI) ? 0x00       : SCIF_DR)

Makes sense, as SCIF_RDxF_CLEAR already includes SCIF_DR, and we thus already
clear both RDF and DR.

However, if you would handle this inside the SCxSR_RDxF() macro, your patch
would reduce to a single line:

-#define SCxSR_RDxF(port)        (((port)->type == PORT_SCI) ?
SCI_RDRF   : SCIF_RDF)
+#define SCxSR_RDxF(port)        (((port)->type == PORT_SCI) ?
SCI_RDRF   : SCIF_DR | SCIF_RDF)

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
diff mbox

Patch

diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 385afbe..de25db8 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -677,7 +677,7 @@  static int sci_poll_get_char(struct uart_port *port)
 		break;
 	} while (1);
 
-	if (!(status & SCxSR_RDxF(port)))
+	if (!(status & (SCxSR_RDxF(port) | SCxSR_DR(port))))
 		return NO_POLL_CHAR;
 
 	c = serial_port_in(port, SCxRDR);
@@ -773,7 +773,8 @@  static int sci_rxfill(struct uart_port *port)
 	if (reg->size)
 		return serial_port_in(port, SCFDR) & ((port->fifosize << 1) - 1);
 
-	return (serial_port_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
+	return (serial_port_in(port, SCxSR) &
+		(SCxSR_RDxF(port) | SCxSR_DR(port))) != 0;
 }
 
 /*
@@ -864,7 +865,7 @@  static void sci_receive_chars(struct uart_port *port)
 	unsigned char flag;
 
 	status = serial_port_in(port, SCxSR);
-	if (!(status & SCxSR_RDxF(port)))
+	if (!(status & (SCxSR_RDxF(port) | SCxSR_DR(port))))
 		return;
 
 	while (1) {
@@ -1672,7 +1673,7 @@  static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
 	 * Rx Interrupt: if we're using DMA, the DMA controller clears RDF /
 	 * DR flags
 	 */
-	if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) &&
+	if (((ssr_status & (SCxSR_RDxF(port) | SCxSR_DR(port))) || s->chan_rx) &&
 	    (scr_status & SCSCR_RIE))
 		ret = sci_rx_interrupt(irq, ptr);
 
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h
index f51f919..44997a5 100644
--- a/drivers/tty/serial/sh-sci.h
+++ b/drivers/tty/serial/sh-sci.h
@@ -156,6 +156,7 @@  enum {
 #define SCxSR_FER(port)		(((port)->type == PORT_SCI) ? SCI_FER    : SCIF_FER)
 #define SCxSR_PER(port)		(((port)->type == PORT_SCI) ? SCI_PER    : SCIF_PER)
 #define SCxSR_BRK(port)		(((port)->type == PORT_SCI) ? 0x00       : SCIF_BRK)
+#define SCxSR_DR(port)		(((port)->type == PORT_SCI) ? 0x00       : SCIF_DR)
 
 #define SCxSR_ERRORS(port)	(to_sci_port(port)->error_mask)